diff options
| -rw-r--r-- | .gitignore | 44 | ||||
| -rw-r--r-- | .gitmodules | 14 | ||||
| -rw-r--r-- | config/Xdefaults (renamed from Xdefaults) | 0 | ||||
| l--------- | config/alacritty/alacritty | 1 | ||||
| -rw-r--r-- | config/alacritty/alacritty.toml (renamed from alacritty/alacritty.toml) | 0 | ||||
| -rw-r--r-- | config/bash_aliases (renamed from bash_aliases) | 0 | ||||
| -rw-r--r-- | config/bash_profile (renamed from bash_profile) | 0 | ||||
| -rw-r--r-- | config/bashrc (renamed from bashrc) | 0 | ||||
| -rw-r--r-- | config/emacs/.emacs.desktop.lock | 1 | ||||
| l--------- | config/emacs/emacs | 1 | ||||
| -rw-r--r-- | config/emacs/eshell/alias (renamed from emacs/eshell/alias) | 0 | ||||
| -rw-r--r-- | config/emacs/eshell/profile (renamed from emacs/eshell/profile) | 0 | ||||
| -rw-r--r-- | config/emacs/history | 22 | ||||
| -rw-r--r-- | config/emacs/init.el (renamed from emacs/init.el) | 0 | ||||
| -rw-r--r-- | config/emacs/site-lisp/chinese.el (renamed from emacs/site-lisp/chinese.el) | 0 | ||||
| -rw-r--r-- | config/emacs/site-lisp/fbterm.el (renamed from emacs/site-lisp/fbterm.el) | 0 | ||||
| -rw-r--r-- | config/emacs/site-lisp/maze.el (renamed from emacs/site-lisp/maze.el) | 0 | ||||
| -rw-r--r-- | config/emacs/site-lisp/my-eglot.el (renamed from emacs/site-lisp/my-eglot.el) | 0 | ||||
| -rw-r--r-- | config/emacs/site-lisp/my-exwm.el (renamed from emacs/site-lisp/my-exwm.el) | 0 | ||||
| -rw-r--r-- | config/emacs/site-lisp/my-mail.el (renamed from emacs/site-lisp/my-mail.el) | 0 | ||||
| -rw-r--r-- | config/emacs/site-lisp/my-modal.el (renamed from emacs/site-lisp/my-modal.el) | 3 | ||||
| -rwxr-xr-x | config/emacs/site-lisp/single-header.el (renamed from emacs/site-lisp/single-header.el) | 0 | ||||
| -rw-r--r-- | config/emacs/site-lisp/tex-conf.el (renamed from emacs/site-lisp/tex-conf.el) | 0 | ||||
| -rwxr-xr-x | config/emacs/site-lisp/tmu-custom-theme.el (renamed from emacs/site-lisp/tmu-custom-theme.el) | 0 | ||||
| -rw-r--r-- | config/emacs/splashLaputa.png (renamed from emacs/splashLaputa.png) | bin | 376185 -> 376185 bytes | |||
| -rw-r--r-- | config/emacs/templates/c.eld (renamed from emacs/templates/c.eld) | 0 | ||||
| -rw-r--r-- | config/emacs/viper | 1 | ||||
| -rwxr-xr-x | config/fbterm/fbterm-emacs.sh (renamed from fbterm/fbterm-emacs.sh) | 0 | ||||
| -rw-r--r-- | config/fbterm/fbtermrc (renamed from fbterm/fbtermrc) | 0 | ||||
| -rw-r--r-- | config/firefox/chrome/userChrome.css (renamed from firefox/chrome/userChrome.css) | 0 | ||||
| -rw-r--r-- | config/firefox/user.js (renamed from firefox/user.js) | 0 | ||||
| -rw-r--r-- | config/foot/foot.ini (renamed from foot/foot.ini) | 0 | ||||
| -rw-r--r-- | config/glide/glide.d.ts | 13955 | ||||
| -rw-r--r-- | config/glide/glide.ts (renamed from glide/glide.ts) | 0 | ||||
| -rw-r--r-- | config/glirc/config | 18 | ||||
| -rw-r--r-- | config/qutebrowser/autoconfig.yml (renamed from qutebrowser/autoconfig.yml) | 0 | ||||
| -rw-r--r-- | config/qutebrowser/bookmarks/urls (renamed from qutebrowser/bookmarks/urls) | 0 | ||||
| -rw-r--r-- | config/qutebrowser/quickmarks (renamed from qutebrowser/quickmarks) | 0 | ||||
| l--------- | config/qutebrowser/qutebrowser | 1 | ||||
| -rw-r--r-- | config/sway/config (renamed from sway/config) | 0 | ||||
| -rwxr-xr-x | config/sway/otherwindow (renamed from sway/otherwindow) | 0 | ||||
| -rwxr-xr-x | config/sway/switch.py (renamed from sway/switch.py) | 0 | ||||
| -rwxr-xr-x | config/sway/switch.sh (renamed from sway/switch.sh) | 0 | ||||
| -rwxr-xr-x | config/sway/toEmacs.sh (renamed from sway/toEmacs.sh) | 0 | ||||
| -rw-r--r-- | config/vimb/_style.css (renamed from vimb/_style.css) | 0 | ||||
| -rw-r--r-- | config/vimb/config (renamed from vimb/config) | 0 | ||||
| -rw-r--r-- | config/vimb/scripts.js (renamed from vimb/scripts.js) | 0 | ||||
| -rw-r--r-- | config/vimb/vimb/_style.css (renamed from vimb/vimb/_style.css) | 0 | ||||
| -rw-r--r-- | config/vimb/vimb/config (renamed from vimb/vimb/config) | 0 | ||||
| -rw-r--r-- | config/waybar/config (renamed from waybar/config) | 0 | ||||
| -rwxr-xr-x | config/waybar/mediaplayer.py (renamed from waybar/mediaplayer.py) | 0 | ||||
| -rw-r--r-- | config/waybar/style.css (renamed from waybar/style.css) | 0 | ||||
| -rw-r--r-- | config/xinitrc (renamed from xinitrc) | 0 | ||||
| -rw-r--r-- | config/xmobarrc (renamed from xmobarrc) | 0 | ||||
| -rw-r--r-- | config/xmonad/xmonad.cabal (renamed from xmonad/xmonad.cabal) | 0 | ||||
| -rw-r--r-- | config/xmonad/xmonad.hs (renamed from xmonad/xmonad.hs) | 0 | ||||
| -rw-r--r-- | dwm/dwm-6.6.tar.gz | bin | 26379 -> 0 bytes | |||
| -rw-r--r-- | dwm/dwm-6.6/LICENSE | 38 | ||||
| -rw-r--r-- | dwm/dwm-6.6/Makefile | 45 | ||||
| -rw-r--r-- | dwm/dwm-6.6/README | 48 | ||||
| -rw-r--r-- | dwm/dwm-6.6/config.def.h | 136 | ||||
| -rw-r--r-- | dwm/dwm-6.6/config.mk | 39 | ||||
| -rw-r--r-- | dwm/dwm-6.6/drw.c | 448 | ||||
| -rw-r--r-- | dwm/dwm-6.6/drw.h | 58 | ||||
| -rw-r--r-- | dwm/dwm-6.6/dwm.1 | 176 | ||||
| -rw-r--r-- | dwm/dwm-6.6/dwm.c | 2277 | ||||
| -rw-r--r-- | dwm/dwm-6.6/dwm.png | bin | 373 -> 0 bytes | |||
| -rw-r--r-- | dwm/dwm-6.6/movestack.c | 49 | ||||
| -rw-r--r-- | dwm/dwm-6.6/transient.c | 42 | ||||
| -rw-r--r-- | dwm/dwm-6.6/util.c | 37 | ||||
| -rw-r--r-- | dwm/dwm-6.6/util.h | 9 | ||||
| -rwxr-xr-x | dwm/setup.sh | 9 | ||||
| -rwxr-xr-x | niceties/capslock/caps2esc | 7 | ||||
| m--------- | niceties/capslock/caps2esc-tools | 0 | ||||
| -rwxr-xr-x | niceties/capslock/caps2escd | 5 | ||||
| m--------- | niceties/capslock/interception-tools | 0 | ||||
| -rw-r--r-- | niceties/capslock/udevmon.yaml | 6 | ||||
| -rwxr-xr-x | niceties/setup.sh | 25 | ||||
| m--------- | niceties/unclutter-xfixes | 0 | ||||
| -rwxr-xr-x | scripts/brightness/brightnessdown (renamed from brightness/brightnessdown) | 0 | ||||
| -rwxr-xr-x | scripts/brightness/brightnessmax (renamed from brightness/brightnessmax) | 0 | ||||
| -rwxr-xr-x | scripts/brightness/brightnessup (renamed from brightness/brightnessup) | 0 | ||||
| -rwxr-xr-x | scripts/misc/lk.sh (renamed from misc/lk.sh) | 0 | ||||
| -rwxr-xr-x | scripts/volume/volumedown (renamed from volume/volumedown) | 0 | ||||
| -rwxr-xr-x | scripts/volume/volumemute (renamed from volume/volumemute) | 0 | ||||
| -rwxr-xr-x | scripts/volume/volumeup (renamed from volume/volumeup) | 0 | ||||
| -rwxr-xr-x | setup.sh | 62 | ||||
| -rwxr-xr-x | slstatus/setup.sh | 9 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1.tar.gz | bin | 18407 -> 0 bytes | |||
| -rw-r--r-- | slstatus/slstatus-1.1/LICENSE | 46 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/Makefile | 69 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/README | 65 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/arg.h | 33 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/components/battery.c | 247 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/components/cat.c | 32 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/components/cpu.c | 157 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/components/datetime.c | 20 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/components/disk.c | 59 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/components/entropy.c | 29 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/components/hostname.c | 17 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/components/ip.c | 87 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/components/kernel_release.c | 19 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/components/keyboard_indicators.c | 50 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/components/keymap.c | 86 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/components/load_avg.c | 19 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/components/netspeeds.c | 129 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/components/num_files.c | 32 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/components/ram.c | 212 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/components/run_command.c | 31 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/components/swap.c | 274 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/components/temperature.c | 73 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/components/uptime.c | 34 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/components/user.c | 33 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/components/volume.c | 219 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/components/wifi.c | 413 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/config.def.h | 74 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/config.mk | 22 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/slstatus.1 | 47 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/slstatus.c | 135 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/slstatus.h | 85 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/util.c | 141 | ||||
| -rw-r--r-- | slstatus/slstatus-1.1/util.h | 16 | ||||
| -rwxr-xr-x | st/setup.sh | 9 | ||||
| -rw-r--r-- | st/st-0.9.3.tar.gz | bin | 49528 -> 0 bytes | |||
| -rw-r--r-- | st/st-0.9.3/FAQ | 253 | ||||
| -rw-r--r-- | st/st-0.9.3/LEGACY | 17 | ||||
| -rw-r--r-- | st/st-0.9.3/LICENSE | 34 | ||||
| -rw-r--r-- | st/st-0.9.3/Makefile | 51 | ||||
| -rw-r--r-- | st/st-0.9.3/README | 34 | ||||
| -rw-r--r-- | st/st-0.9.3/TODO | 28 | ||||
| -rw-r--r-- | st/st-0.9.3/arg.h | 50 | ||||
| -rw-r--r-- | st/st-0.9.3/config.def.h | 503 | ||||
| -rw-r--r-- | st/st-0.9.3/config.mk | 36 | ||||
| -rw-r--r-- | st/st-0.9.3/st.1 | 177 | ||||
| -rw-r--r-- | st/st-0.9.3/st.c | 3414 | ||||
| -rw-r--r-- | st/st-0.9.3/st.h | 136 | ||||
| -rw-r--r-- | st/st-0.9.3/st.info | 244 | ||||
| -rw-r--r-- | st/st-0.9.3/win.h | 44 | ||||
| -rw-r--r-- | st/st-0.9.3/x.c | 2532 | ||||
| -rw-r--r-- | symlinks.csv | 34 | ||||
| -rwxr-xr-x | xmonad/build | 3 |
141 files changed, 14078 insertions, 14112 deletions
@@ -2,32 +2,18 @@ *.o TAGS -xmonad/build-x86_64-linux/ -xmonad/dist-newstyle/ -xmonad/xmonad-x86_64-linux -xmonad/xmonad.errors - -emacs/.cache/ -emacs/.lsp-session-v1 -emacs/tramp -emacs/tree-sitter/ -emacs/transient/ -emacs/recentf -emacs/recentf.eld -emacs/projects.eld -emacs/elpa -emacs/eln-cache -emacs/auto-save-list -emacs/bookmarks.eld -emacs/url/ -emacs/eshell/history -emacs/eshell/lastdir - -slstatus/*/config.h -slstatus/*/slstatus - -st/*/config.h -st/*/st - -dwm/*/config.h -dwm/*/dwm +config/emacs/.cache/ +config/emacs/.lsp-session-v1 +config/emacs/tramp +config/emacs/tree-sitter/ +config/emacs/transient/ +config/emacs/recentf +config/emacs/recentf.eld +config/emacs/projects.eld +config/emacs/elpa +config/emacs/eln-cache +config/emacs/auto-save-list +config/emacs/bookmarks.eld +config/emacs/url/ +config/emacs/eshell/history +config/emacs/eshell/lastdir diff --git a/.gitmodules b/.gitmodules index 81c3985..fc9aa05 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,12 +1,18 @@ [submodule "emacs-source"] - path = emacs-source + path = tree/src/emacs/emacs-source url = git://git.savannah.gnu.org/emacs.git [submodule "capslock/interception-tools"] - path = niceties/capslock/interception-tools + path = tree/src/capslock/interception-tools url = https://gitlab.com/interception/linux/tools [submodule "capslock/caps2esc"] - path = niceties/capslock/caps2esc-tools + path = tree/src/capslock/caps2esc-tools url = https://gitlab.com/interception/linux/plugins/caps2esc [submodule "niceties/unclutter-xfixes"] - path = niceties/unclutter-xfixes + path = tree/src/unclutter-xfixes url = https://github.com/Airblader/unclutter-xfixes +[submodule "tree/src/tcc/tcc"] + path = tree/src/tcc/tcc + url = https://repo.or.cz/tinycc.git +[submodule "tree/src/microhs/microhs"] + path = tree/src/microhs/microhs + url = https://github.com/augustss/MicroHs diff --git a/Xdefaults b/config/Xdefaults index 8ba8341..8ba8341 100644 --- a/Xdefaults +++ b/config/Xdefaults diff --git a/config/alacritty/alacritty b/config/alacritty/alacritty new file mode 120000 index 0000000..c15d976 --- /dev/null +++ b/config/alacritty/alacritty @@ -0,0 +1 @@ +/home/tmu/dotfiles/config/alacritty
\ No newline at end of file diff --git a/alacritty/alacritty.toml b/config/alacritty/alacritty.toml index 72e4f07..72e4f07 100644 --- a/alacritty/alacritty.toml +++ b/config/alacritty/alacritty.toml diff --git a/bash_aliases b/config/bash_aliases index e6d95a0..e6d95a0 100644 --- a/bash_aliases +++ b/config/bash_aliases diff --git a/bash_profile b/config/bash_profile index 88f4ed4..88f4ed4 100644 --- a/bash_profile +++ b/config/bash_profile diff --git a/config/emacs/.emacs.desktop.lock b/config/emacs/.emacs.desktop.lock new file mode 100644 index 0000000..f1904f0 --- /dev/null +++ b/config/emacs/.emacs.desktop.lock @@ -0,0 +1 @@ +7862
\ No newline at end of file diff --git a/config/emacs/emacs b/config/emacs/emacs new file mode 120000 index 0000000..2514d29 --- /dev/null +++ b/config/emacs/emacs @@ -0,0 +1 @@ +/home/tmu/dotfiles/config/emacs
\ No newline at end of file diff --git a/emacs/eshell/alias b/config/emacs/eshell/alias index 6dcd5cf..6dcd5cf 100644 --- a/emacs/eshell/alias +++ b/config/emacs/eshell/alias diff --git a/emacs/eshell/profile b/config/emacs/eshell/profile index 8b13789..8b13789 100644 --- a/emacs/eshell/profile +++ b/config/emacs/eshell/profile diff --git a/config/emacs/history b/config/emacs/history new file mode 100644 index 0000000..e7d5648 --- /dev/null +++ b/config/emacs/history @@ -0,0 +1,22 @@ +;; -*- mode: emacs-lisp; lexical-binding: t; coding: utf-8-emacs-unix -*- +;; Minibuffer history file, automatically generated by ‘savehist’. + +(setq savehist-minibuffer-history-variables '(shell-command-history read-number-history regexp-history substitute--history viper-ex-history viper-search-history query-replace-history minibuffer-history bookmark-history Man-topic-history read-expression-history grep-regexp-history yes-or-no-p-history extended-command-history file-name-history buffer-name-history)) +(setq shell-command-history '("pwd")) +(setq regexp-history '("advice")) +(setq substitute--history '("VIPER")) +(setq viper-ex-history '("25,43s/d/D" "25,36p" "pr" "rp" "1" ",$p" "2" "0," ",$p" "s/old/new" ",$s/viper/VIPER" ",$/s/viper/VIPER" ",$ p" "b" "!fortune" "s/viper/VIPER" "s/viper Viper" "s/viper/Viper" "<,>s/viper/VIPER")) +(setq viper-search-history '(#("syntax-preference 'emacs) + (setq-default viper-ex-style-motion nil) + (setq-default viper-auto-indent t) + (setq-default viper-" 0 29 (fontified t) 29 41 (face font-lock-keyword-face fontified t) 41 72 (fontified t) 72 84 (face font-lock-keyword-face fontified t) 84 109 (fontified t) 109 121 (face font-lock-keyword-face fontified t) 121 128 (fontified t)) "viper" "")) +(setq query-replace-history '("#define \\1 0" #("^ *\\([A-Z_]*\\b\\).*" 3 4 (syntax-table #1=(3)) 14 15 (syntax-table #1#)))) +(setq minibuffer-history '("viper" "call-interactively" "default-directory" "save-excursion" "elisp" "with-local-quit" "call-interactively" "add-function" "viper-ex" "add-function" "funcall-interactively" "add-function" "viper-ex" "add-function" "advice-add" "defadvice" "advice-add" "advice--called-interactively-skip" "call-interactively" "funcall-interactively" "viper-ex" "funcall" "call-interactively" "with-local-quit" "elisp" "condition-case" "ignore-errors" "ignore-error" "elisp" "catch" "advice-add" "display-line-numbers-mode" "display-line-numbers" "advice-add" "ex-substitute" "viper-ex" "viper-mode" "viper-always" "viper" "substitute-0.5.0" "viper-substitute" "tmu-custom")) +(setq bookmark-history '("init.el")) +(setq Man-topic-history '("exec" "dbus-launch")) +(setq read-expression-history '("(project-root (project-current))" "(require 'substitute)" "(setq before-save-hook nil)")) +(setq grep-regexp-history '("XDG_RUNTIME")) +(setq yes-or-no-p-history '("yes" "no" "yes")) +(setq extended-command-history '("my/shell-at-root" "free-keys" "toggle-debug-on-quit" "viper-ex" "toggle-viper-mode" "viper-mode" "display-line-numbers-mode" "package-delete" "substitute-target-to-beginning-of-buffer" "list-packages" "toggle-viper-mode" "emacs-lock-mode" "emacs-build-description" "my/start-erc" "load-file" "describe-char" "list-colors-display" "describe-theme" "package-upgrade-all" "package-refresh-contents" "c-mode" "man" "desktop-remove" "desktop-read" "desktop-save" "bash-ts-mode" "package-autoremove")) +(setq file-name-history '("~/Desktop/musl/src/math/arm/fma.c" "~/.emacs.d/init.el" "~/.local/share/emacs/31.0.50/lisp/emacs-lisp/advice.el.gz" "~/.emacs.d/init.el" "~/.emacs.d/elpa/substitute-0.5.0/substitute-autoloads.el" "~/.local/share/emacs/31.0.50/lisp/emulation/viper-ex.el.gz" "~/.emacs.d/init.el" "/su:root@localhost:/opt/slskd/.local/share/slskd/slskd.yml" "~/.emacs.d/" "/su:root@localhost:/opt/slskd/.local/share/slskd/old.yml" "~/dotfiles/bash_profile" "~/.xinitrc")) +(setq buffer-name-history '("*Completions*" "*vc-diff*" "*info*" " *viper-info*" "*Async Shell Command*" "init.el" "*Async Shell Command*" "fma.c" "*Async Shell Command*" "init.el" "simple.el.gz" "init.el" " *viper-info*" "init.el" "*info*" "*Help*" "viper.el.gz" "init.el" "*Help*" "init.el" "display-line-numbers.el.gz" "*Occur*" "init.el" "*Help*" "init.el" "*Help*" "substitute-0.5.0" "substitute-autoloads.el" "substitute.el" "init.el" "info" "*Packages*" "*Help*" "*Ibuffer*" "#haskell" "Libera.Chat" "#haskell" "old.yml" "Libera.Chat" "*Help*" "slskd.yml" "init.el" "tmu-custom-theme.el" "example" "*vc-dir*" "bash_profile" "*xref*" "*Messages*" "ValveSteamLicense")) diff --git a/emacs/init.el b/config/emacs/init.el index 27eef38..27eef38 100644 --- a/emacs/init.el +++ b/config/emacs/init.el diff --git a/emacs/site-lisp/chinese.el b/config/emacs/site-lisp/chinese.el index 4b01594..4b01594 100644 --- a/emacs/site-lisp/chinese.el +++ b/config/emacs/site-lisp/chinese.el diff --git a/emacs/site-lisp/fbterm.el b/config/emacs/site-lisp/fbterm.el index b8b3ba4..b8b3ba4 100644 --- a/emacs/site-lisp/fbterm.el +++ b/config/emacs/site-lisp/fbterm.el diff --git a/emacs/site-lisp/maze.el b/config/emacs/site-lisp/maze.el index 784049f..784049f 100644 --- a/emacs/site-lisp/maze.el +++ b/config/emacs/site-lisp/maze.el diff --git a/emacs/site-lisp/my-eglot.el b/config/emacs/site-lisp/my-eglot.el index f4a00a3..f4a00a3 100644 --- a/emacs/site-lisp/my-eglot.el +++ b/config/emacs/site-lisp/my-eglot.el diff --git a/emacs/site-lisp/my-exwm.el b/config/emacs/site-lisp/my-exwm.el index be71f52..be71f52 100644 --- a/emacs/site-lisp/my-exwm.el +++ b/config/emacs/site-lisp/my-exwm.el diff --git a/emacs/site-lisp/my-mail.el b/config/emacs/site-lisp/my-mail.el index bcda232..bcda232 100644 --- a/emacs/site-lisp/my-mail.el +++ b/config/emacs/site-lisp/my-mail.el diff --git a/emacs/site-lisp/my-modal.el b/config/emacs/site-lisp/my-modal.el index 52cf8d3..1803609 100644 --- a/emacs/site-lisp/my-modal.el +++ b/config/emacs/site-lisp/my-modal.el @@ -208,4 +208,5 @@ (defun ryo-modal-unless-minibuffer () (unless (minibufferp) (ryo-modal-mode 1))) - (add-hook 'after-change-major-mode-hook 'ryo-modal-unless-minibuffer)) + ;; (add-hook 'after-change-major-mode-hook 'ryo-modal-unless-minibuffer) + ) diff --git a/emacs/site-lisp/single-header.el b/config/emacs/site-lisp/single-header.el index dc65335..dc65335 100755 --- a/emacs/site-lisp/single-header.el +++ b/config/emacs/site-lisp/single-header.el diff --git a/emacs/site-lisp/tex-conf.el b/config/emacs/site-lisp/tex-conf.el index 4592ce5..4592ce5 100644 --- a/emacs/site-lisp/tex-conf.el +++ b/config/emacs/site-lisp/tex-conf.el diff --git a/emacs/site-lisp/tmu-custom-theme.el b/config/emacs/site-lisp/tmu-custom-theme.el index 965d7c8..965d7c8 100755 --- a/emacs/site-lisp/tmu-custom-theme.el +++ b/config/emacs/site-lisp/tmu-custom-theme.el diff --git a/emacs/splashLaputa.png b/config/emacs/splashLaputa.png Binary files differindex 4b5de18..4b5de18 100644 --- a/emacs/splashLaputa.png +++ b/config/emacs/splashLaputa.png diff --git a/emacs/templates/c.eld b/config/emacs/templates/c.eld index fdb899f..fdb899f 100644 --- a/emacs/templates/c.eld +++ b/config/emacs/templates/c.eld diff --git a/config/emacs/viper b/config/emacs/viper new file mode 100644 index 0000000..feadc7d --- /dev/null +++ b/config/emacs/viper @@ -0,0 +1 @@ +(setq viper-inhibit-startup-message 't) diff --git a/fbterm/fbterm-emacs.sh b/config/fbterm/fbterm-emacs.sh index 91616b3..91616b3 100755 --- a/fbterm/fbterm-emacs.sh +++ b/config/fbterm/fbterm-emacs.sh diff --git a/fbterm/fbtermrc b/config/fbterm/fbtermrc index 777071f..777071f 100644 --- a/fbterm/fbtermrc +++ b/config/fbterm/fbtermrc diff --git a/firefox/chrome/userChrome.css b/config/firefox/chrome/userChrome.css index 510b37d..510b37d 100644 --- a/firefox/chrome/userChrome.css +++ b/config/firefox/chrome/userChrome.css diff --git a/firefox/user.js b/config/firefox/user.js index 9045107..9045107 100644 --- a/firefox/user.js +++ b/config/firefox/user.js diff --git a/foot/foot.ini b/config/foot/foot.ini index e07855c..e07855c 100644 --- a/foot/foot.ini +++ b/config/foot/foot.ini diff --git a/config/glide/glide.d.ts b/config/glide/glide.d.ts new file mode 100644 index 0000000..db2d26f --- /dev/null +++ b/config/glide/glide.d.ts @@ -0,0 +1,13955 @@ +/* ====================================================== + Glide version: 0.1.52a + ====================================================== */ + +declare const GLIDE_EXCOMMANDS: [ + { + readonly name: "back"; + readonly description: "Go back one page in history"; + readonly content: false; + readonly repeatable: true; + }, + { + readonly name: "forward"; + readonly description: "Go forward one page in history"; + readonly content: false; + readonly repeatable: true; + }, + { + readonly name: "reload"; + readonly description: "Reload the current page"; + readonly content: false; + readonly repeatable: true; + }, + { + readonly name: "reload_hard"; + readonly description: "Reload the current page, bypassing the cache"; + readonly content: false; + readonly repeatable: true; + }, + { + readonly name: "quit"; + readonly description: "Close all windows"; + readonly content: false; + readonly repeatable: false; + }, + { + readonly name: "clear"; + readonly description: "Clear all notifications"; + readonly content: false; + readonly repeatable: false; + }, + { + readonly name: "set"; + readonly description: "Set an option"; + readonly args_schema: { + readonly name: { + readonly type: "string"; + readonly position: 0; + readonly required: true; + }; + readonly value: { + readonly type: "string"; + readonly position: 1; + readonly required: true; + }; + }; + readonly content: false; + readonly repeatable: false; + }, + { + readonly name: "profile_dir"; + readonly description: "Show the current profile directory"; + readonly content: false; + readonly repeatable: false; + }, + { + readonly name: "config_edit"; + readonly description: "Open the config file in the default editor"; + readonly content: false; + readonly repeatable: false; + }, + { + readonly name: "config_path"; + readonly description: "Show the config file path"; + readonly content: false; + readonly repeatable: false; + }, + { + readonly name: "config_reload"; + readonly description: "Reload the config file"; + readonly content: false; + readonly repeatable: false; + }, + { + readonly name: "config_init"; + readonly description: "Initialise a config dir with all the necessary setup"; + readonly args_schema: { + readonly location: { + readonly type: { + readonly enum: readonly [ + "home", + "profile", + "cwd" + ]; + }; + readonly required: false; + readonly position: 0; + }; + }; + readonly content: false; + readonly repeatable: false; + }, + { + readonly name: "css_edit"; + readonly description: "Open the userChrome.css file in the default editor"; + readonly content: false; + readonly repeatable: false; + }, + { + readonly name: "repeat"; + readonly description: "Repeat the last invoked command. In general only applies to \"mutative\" commands"; + readonly content: false; + readonly repeatable: false; + }, + { + readonly name: "map"; + readonly description: "Show all mappings"; + readonly content: false; + readonly repeatable: false; + }, + { + readonly name: "unmap"; + readonly description: "Remove a mapping from normal mode"; + readonly args_schema: { + readonly lhs: { + readonly type: "string"; + readonly required: true; + readonly position: 0; + }; + }; + readonly content: false; + readonly repeatable: false; + }, + { + readonly name: "nunmap"; + readonly description: "Remove a mapping from normal mode"; + readonly args_schema: { + readonly lhs: { + readonly type: "string"; + readonly required: true; + readonly position: 0; + }; + }; + readonly content: false; + readonly repeatable: false; + }, + { + readonly name: "iunmap"; + readonly description: "Remove a mapping from insert mode"; + readonly args_schema: { + readonly lhs: { + readonly type: "string"; + readonly required: true; + readonly position: 0; + }; + }; + readonly content: false; + readonly repeatable: false; + }, + { + readonly name: "tab"; + readonly description: "Switch to the given tab index"; + readonly args_schema: { + readonly tab_index: { + readonly type: "integer"; + readonly required: true; + readonly position: 0; + }; + }; + readonly content: false; + readonly repeatable: false; + }, + { + readonly name: "tab_new"; + readonly description: "Create a new tab with the given URL or the default new tab page if not provided"; + readonly args_schema: { + readonly url: { + readonly type: "string"; + readonly required: false; + readonly position: 0; + }; + }; + readonly content: false; + readonly repeatable: false; + }, + { + readonly name: "tab_close"; + readonly description: "Close the current tab"; + readonly content: false; + readonly repeatable: true; + }, + { + readonly name: "tab_next"; + readonly description: "Switch to the next tab, wrapping around if applicable"; + readonly content: false; + readonly repeatable: true; + }, + { + readonly name: "tab_prev"; + readonly description: "Switch to the previous tab, wrapping around if applicable"; + readonly content: false; + readonly repeatable: true; + }, + { + readonly name: "commandline_show"; + readonly description: "Show the commandline UI"; + readonly content: false; + readonly args_schema: {}; + readonly repeatable: false; + }, + { + readonly name: "commandline_toggle"; + readonly description: "Toggle the commandline UI"; + readonly content: false; + readonly args_schema: {}; + readonly repeatable: false; + }, + { + readonly name: "commandline_focus_next"; + readonly description: "Focus the next completion in the commandline"; + readonly content: false; + readonly args_schema: {}; + readonly repeatable: false; + }, + { + readonly name: "commandline_focus_back"; + readonly description: "Focus the previous completion in the commandline"; + readonly content: false; + readonly args_schema: {}; + readonly repeatable: false; + }, + { + readonly name: "commandline_delete"; + readonly description: "Delete the focused commandline completion"; + readonly content: false; + readonly args_schema: {}; + readonly repeatable: false; + }, + { + readonly name: "commandline_accept"; + readonly description: "Accept the focused commandline completion"; + readonly content: false; + readonly args_schema: {}; + readonly repeatable: false; + }, + { + readonly name: "url_yank"; + readonly description: "Yank the URL of the current tab to the clipboard"; + readonly content: false; + readonly repeatable: false; + }, + { + readonly name: "echo"; + readonly description: "Log the given arguments to the console"; + readonly content: false; + readonly args_schema: {}; + readonly repeatable: false; + }, + { + readonly name: "mode_change"; + readonly description: "Change the current mode"; + readonly content: false; + readonly repeatable: false; + readonly args_schema: { + readonly mode: { + readonly type: { + readonly enum: GlideMode[]; + }; + readonly required: true; + readonly position: 0; + }; + readonly "--automove": { + readonly type: { + readonly enum: readonly [ + "left", + "endline" + ]; + }; + readonly required: false; + }; + readonly "--operator": { + readonly type: { + readonly enum: readonly [ + "d", + "c", + "r" + ]; + }; + readonly required: false; + readonly description: "Only applicable for operator-pending mode"; + }; + }; + }, + { + readonly name: "caret_move"; + readonly description: "Move the text caret"; + readonly content: false; + readonly repeatable: false; + readonly args_schema: { + readonly direction: { + readonly type: { + readonly enum: readonly [ + "left", + "right", + "up", + "down" + ]; + }; + readonly required: true; + readonly position: 0; + }; + }; + }, + { + readonly name: "visual_selection_copy"; + readonly description: "Copy the currently selected text to the clipboard & change to normal mode"; + readonly content: false; + readonly repeatable: false; + }, + { + readonly name: "help"; + readonly description: "Open the docs"; + readonly content: false; + readonly repeatable: false; + }, + { + readonly name: "tutor"; + readonly description: "Open the Glide tutorial"; + readonly content: false; + readonly repeatable: false; + }, + { + readonly name: "repl"; + readonly description: "Start the config REPL"; + readonly content: false; + readonly repeatable: false; + }, + { + readonly name: "keys"; + readonly description: "Synthesize the given key sequence as if they were actually pressed"; + readonly args_schema: { + readonly keyseq: { + readonly type: "string"; + readonly required: true; + readonly position: 0; + }; + }; + readonly content: false; + readonly repeatable: false; + }, + { + readonly name: "r"; + readonly description: "Replace the current character"; + readonly content: false; + readonly repeatable: false; + readonly args_schema: { + readonly character: { + readonly type: "string"; + readonly required: false; + readonly position: 0; + }; + }; + }, + { + readonly name: "scroll_top"; + readonly description: "Scroll to the top of the window"; + readonly content: true; + readonly repeatable: false; + }, + { + readonly name: "scroll_page_down"; + readonly description: "Scroll down by 1 page (the size of the viewport)"; + readonly content: true; + readonly repeatable: false; + }, + { + readonly name: "scroll_page_up"; + readonly description: "Scroll up by 1 page (the size of the viewport)"; + readonly content: true; + readonly repeatable: false; + }, + { + readonly name: "scroll_bottom"; + readonly description: "Scroll to the bottom of the window"; + readonly content: true; + readonly repeatable: false; + }, + { + readonly name: "blur"; + readonly description: "Blur the active element"; + readonly content: true; + readonly repeatable: false; + }, + { + readonly name: "focusinput"; + readonly description: "Focus an input element based on the given filter"; + readonly content: true; + readonly repeatable: false; + readonly args_schema: { + readonly filter: { + readonly type: { + readonly enum: readonly [ + "last" + ]; + }; + readonly required: true; + readonly position: 0; + }; + }; + }, + { + readonly name: "hint"; + readonly description: "Show hint labels for jumping to clickable elements"; + readonly content: false; + readonly repeatable: false; + readonly args_schema: { + readonly "-s": { + readonly type: "string"; + readonly required: false; + readonly description: "*Only* show hints for all elements matching this CSS selector"; + }; + readonly "--include": { + readonly type: "string"; + readonly required: false; + readonly description: "*Also* show hints for all elements matching this CSS selector"; + }; + readonly "-e": { + readonly type: "boolean"; + readonly required: false; + readonly description: "*Only* show hints for all elements that are editable"; + }; + readonly "--auto": { + readonly type: "boolean"; + readonly required: false; + readonly description: "If only one hint is generated, automatically activate it."; + }; + readonly "--action": { + readonly type: { + readonly enum: readonly [ + "click", + "newtab-click" + ]; + }; + readonly required: false; + }; + readonly "--location": { + readonly type: { + readonly enum: readonly [ + "content", + "browser-ui" + ]; + }; + readonly required: false; + }; + }; + }, + { + readonly name: "hints_remove"; + readonly description: "Remove all hint labels and exit hint mode"; + readonly content: false; + readonly repeatable: false; + }, + { + readonly name: "execute_motion"; + readonly description: "Used from op-pending mode to execute a motion."; + readonly content: true; + readonly repeatable: false; + }, + { + readonly name: "motion"; + readonly description: "Execute a given motion (internal)"; + readonly content: true; + readonly repeatable: false; + readonly args_schema: { + readonly keyseq: { + readonly type: { + readonly enum: readonly [ + "w", + "W", + "e", + "b", + "B", + "0", + "$", + "{", + "}", + "s", + "v", + "vh", + "vl", + "vd", + "vc", + "x", + "X", + "o" + ]; + }; + readonly required: true; + readonly position: 0; + }; + }; + }, + { + readonly name: "undo"; + readonly description: "Undo the most recent edit"; + readonly content: false; + readonly repeatable: false; + }, + { + readonly name: "redo"; + readonly description: "Redo the most recent undo"; + readonly content: false; + readonly repeatable: false; + } +]; +export type GlideExcmdName = (typeof GLIDE_EXCOMMANDS)[number]["name"]; +export type GlideCommandString = GlideExcmdName | `${GlideExcmdName} ${string}`; +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +declare global { + var glide: { + ctx: { + /** + * The currently active mode. + */ + mode: GlideMode; + /** + * The URL of the currently focused tab. + */ + url: URL; + /** + * The operating system Glide is running on. + */ + os: "linux" | "win" | "macosx" | "ios" | "android" | "other"; + /** + * Whether or not the currently focused element is editable. + * + * This includes but is not limited to `html:<textarea>`, `html:<input>`, `contenteditable=true`. + */ + is_editing(): Promise<boolean>; + }; + /** + * Set browser-wide options. + */ + /// @docs-expand-type-reference + o: glide.Options; + /** + * Set buffer specific options. + * + * This has the exact same API as {@link glide.o}. + */ + bo: Partial<glide.Options>; + options: { + /** + * Returns either a buffer-specific option, or the global version. In that order + */ + get<Name extends keyof glide.Options>(name: Name): glide.Options[Name]; + }; + env: { + /** + * Get the value of an environment variable. + * + * If it does not exist `null` is returned. + */ + get(name: string): string | null; + /** + * Set the value of an environment variable. + */ + set(name: string, value: string): void; + /** + * Remove an environment variable. + * + * Does *not* error if the environment variable did not already exist. + * + * Returns the value of the deleted environment variable, if it did not exist `null` is returned. + */ + delete(name: string): string | null; + }; + process: { + /** + * Spawn a new process. The given `command` can either be the name of a binary in the `PATH` + * or an absolute path to a binary file. + * + * If the process exits with a non-zero code, an error will be thrown, you can disable this check with `{ check_exit_code: false }`. + * + * ```ts + * const proc = await glide.process.spawn('kitty', ['nvim', 'glide.ts'], { cwd: '~/.dotfiles/glide' }); + * console.log('opened kitty with pid', proc.pid); + * ``` + */ + spawn(command: string, args?: string[] | null | undefined, opts?: glide.SpawnOptions): Promise<glide.Process>; + /** + * Spawn a new process and wait for it to exit. + * + * See {@link glide.process.spawn} for more information. + */ + execute(command: string, args?: string[] | null | undefined, opts?: glide.SpawnOptions): Promise<glide.CompletedProcess>; + }; + autocmds: { + /** + * Create an autocmd that will be invoked whenever the focused URL changes. + * + * This includes: + * 1. URL changes within the same tab + * 2. Switching tabs + * 3. Navigating back and forth in history within the same tab + */ + create<const Event extends "UrlEnter">(event: Event, pattern: glide.AutocmdPatterns[Event], callback: (args: glide.AutocmdArgs[Event]) => void): void; + /** + * Create an autocmd that will be invoked whenever the mode changes. + * + * The pattern is matched against `old_mode:new_mode`. You can also use `*` as a placeholder + * to match *any* mode. + * + * for example, to define an autocmd that will be fired every time visual mode is entered: + * + * `*:visual` + * + * or when visual mode is left: + * + * `visual:*` + * + * or transitioning from visual to insert: + * + * `visual:insert` + * + * or for just any mode: + * + * `*` + */ + create<const Event extends "ModeChanged">(event: Event, pattern: glide.AutocmdPatterns[Event], callback: (args: glide.AutocmdArgs[Event]) => void): void; + /** + * Create an autocmd that will be invoked whenever the key sequence changes. + * + * This will be fired under four circumstances: + * + * 1. A key is pressed that matches a key mapping. + * 2. A key is pressed that is part of a key mapping. + * 3. A key is pressed that cancels a previous partial key mapping sequence. + * 4. A partial key mapping is cancelled (see {@link glide.o.mapping_timeout}) + * + * For example, with + * ```typescript + * glide.keymaps.set('normal', 'gt', '...'); + * ``` + * + * Pressing `g` will fire with `{ sequence: ["g"], partial: true }`, then either: + * - Pressing `t` would fire `{ sequence: ["g", "t"], partial: false }` + * - Pressing any other key would fire `{ sequence: [], partial: false }` + * + * Note that this is not fired for consecutive key presses for keys that don't correspond to mappings, + * as the key state has not changed. + */ + create<const Event extends "KeyStateChanged">(event: Event, callback: (args: glide.AutocmdArgs[Event]) => void): void; + /** + * Create an autocmd that will be invoked whenever the config is loaded. + * + * Called once on initial load and again every time the config is reloaded. + */ + create<const Event extends "ConfigLoaded">(event: Event, callback: (args: glide.AutocmdArgs[Event]) => void): void; + /** + * Create an autocmd that will be invoked when the window is initially loaded. + * + * **note**: this is not invoked when the config is reloaded. + */ + create<const Event extends "WindowLoaded">(event: Event, callback: (args: glide.AutocmdArgs[Event]) => void): void; + create<const Event extends glide.AutocmdEvent>(event: Event, pattern: glide.AutocmdPatterns[Event] extends never ? (args: glide.AutocmdArgs[Event]) => void : glide.AutocmdPatterns[Event], callback?: (args: glide.AutocmdArgs[Event]) => void): void; + }; + prefs: { + /** + * Set a preference. This is an alternative to `prefs.js` / [`about:config`](https://support.mozilla.org/en-US/kb/about-config-editor-firefox) so + * that all customisation can be represented in a single `glide.ts` file. + * + * **warning**: this function is expected to be called at the top-level of your config, there is no guarantee that calling {@link glide.prefs.set} in callbacks + * will result in the pref being properly applied everywhere. + * + * **warning**: there is also no guarantee that these settings will be applied when first loaded, sometimes a restart is required. + */ + set(name: string, value: string | number | boolean): void; + /** + * Get the value of a pref. + * + * If the pref is not defined, then `undefined` is returned. + */ + get(name: string): string | number | boolean | undefined; + /** + * Reset the pref value back to its default. + */ + clear(name: string): void; + }; + /** + * Equivalent to `vim.g`. + * + * You can also store arbitrary data here in a typesafe fashion with: + * ```ts + * declare global { + * interface GlideGlobals { + * my_prop?: boolean; + * } + * } + * glide.g.my_prop = true; + * ``` + */ + /// @docs-expand-type-reference + g: GlideGlobals; + tabs: { + /** + * Returns the active tab for the currently focused window. + * + * This is equivalent to: + * ```ts + * const tab = await browser.tabs.query({ active: true, currentWindow: true })[0]; + * ``` + * But with additional error handling for invalid states. + */ + active(): Promise<glide.TabWithID>; + /** + * Find the first tab matching the given query filter. + * + * This is the same API as [browser.tabs.get](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/get), + * but returns the first tab instead of an Array. + */ + get_first(query: Browser.Tabs.QueryQueryInfoType): Promise<Browser.Tabs.Tab | undefined>; + /** + * Gets all tabs that have the specified properties, or all tabs if no properties are specified. + * + * This is the same API as [browser.tabs.get](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/query), + */ + query(query: Browser.Tabs.QueryQueryInfoType): Promise<Browser.Tabs.Tab[]>; + }; + excmds: { + /** + * Execute an excmd, this is the same as typing `:cmd --args`. + */ + execute(cmd: glide.ExcmdString): Promise<void>; + /** + * Create a new excmd. + * + * e.g. + * ```typescript + * const cmd = glide.excmds.create( + * { name: "my_excmd", description: "..." }, + * () => { + * // ... + * } + * ); + * declare global { + * interface ExcmdRegistry { + * my_excmd: typeof cmd; + * } + * } + * ``` + */ + create<const Excmd extends glide.ExcmdCreateProps>(info: Excmd, fn: (props: glide.ExcmdCallbackProps) => void | Promise<void>): Excmd; + }; + content: { + /** + * Execute a function in the content process for the given tab. + * + * The given function will be stringified before being sent across processes, which + * means it **cannot** capture any outside variables. + * + * If you need to pass some context into the function, use `args`, e.g. + * + * ```ts + * function set_body_border_style(css: string) { + * document.body.style.setProperty('border', css) + * } + * await glide.content.execute(set_body_border_style, { tab_id, args: ["20px dotted pink"] }) + * ``` + * + * Note: all `args` must be JSON serialisable. + */ + execute<F extends (...args: any[]) => any>(func: F, opts: { + /** + * The ID of the tab into which to inject. + * + * Or the tab object as returned by {@link glide.tabs.active}. + */ + tab_id: number | glide.TabWithID; + } & (Parameters<F> extends [ + ] ? { + /** + * Note: the given function doesn't take any arguments but if + * it did, you could pass them here. + */ + args?: undefined; + } : { + /** + * Arguments to pass to the given function. + * + * **Must** be JSON serialisable + */ + args: Parameters<F>; + })): Promise<ReturnType<F>>; + }; + keymaps: { + set<const LHS>(modes: GlideMode | GlideMode[], lhs: $keymapcompletions.T<LHS>, rhs: glide.ExcmdString | glide.KeymapCallback, opts?: glide.KeymapOpts | undefined): void; + /** + * Remove the mapping of {lhs} for the {modes} where the map command applies. + * + * The mapping may remain defined for other modes where it applies. + */ + del<const LHS>(modes: GlideMode | GlideMode[], lhs: $keymapcompletions.T<LHS>, opts?: glide.KeymapDeleteOpts): void; + /** + * List all global key mappings. + * + * If a key mapping is defined for multiple modes, multiple entries + * will be returned for each mode. + */ + list(modes?: GlideMode | GlideMode[]): glide.Keymap[]; + }; + hints: { + /** + * Find and show hints for "clickable" elements in the content frame. + * + * An optional `action()` function can be passed that will be invoked when + * a hint is selected. + */ + show(opts?: { + /** + * *Only* show hints for all elements matching this [CSS selector](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_selectors). + * + * @example "li, textarea" + * @example "[id="my-element"]" + */ + selector?: string; + /** + * *Also* show hints for all elements matching this [CSS selector](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_selectors) + * as well as the default set of [hintable elements](https://glide-browser.app/hints#hintable-elements). + * + * @example "li, textarea" + * @example "[id="my-element"]" + */ + include?: string; + /** + * *Only* show hints for elements that are editable. + */ + editable?: boolean; + /** + * If only one hint is generated, automatically activate it. + * + * @default false + */ + auto_activate?: boolean; + /** + * Callback invoked when the selected hint is chosen. + * + * This is executed in the content process. + */ + action?: "click" | "newtab-click" | ((target: HTMLElement) => Promise<void>); + /** + * Which area to generate hints for. + * + * - `content` - Show hints for clickable elements within the web page (links, buttons, etc.) + * - `chrome` - Show hints for browser interface elements (toolbar buttons, tabs, menus, etc.) + * + * @default "content" + */ + location?: glide.HintLocation; + /** + * Define a callback to filter the resolved hints. It is called once with the resolved hints, + * and must return an array of the hints you want to include. + * + * An empty array may be returned but will result in an error notification indicating that no + * hints were found. + * + * @content this function is evaluated in the content process. + */ + pick?: (hints: glide.ContentHint[]) => glide.ContentHint[]; + }): void; + }; + buf: { + prefs: { + /** + * Set a preference for the current buffer. When navigating to a new buffer, the pref will be reset + * to the previous value. + * + * See {@link glide.prefs.set} for more information. + */ + set(name: string, value: string | number | boolean): void; + }; + keymaps: { + set<const LHS>(modes: GlideMode | GlideMode[], lhs: $keymapcompletions.T<LHS>, rhs: glide.ExcmdString | glide.KeymapCallback, opts?: Omit<glide.KeymapOpts, "buffer"> | undefined): void; + /** + * Remove the mapping of {lhs} for the {modes} where the map command applies. + * + * The mapping may remain defined for other modes where it applies. + */ + del(modes: GlideMode | GlideMode[], lhs: string, opts?: Omit<glide.KeymapDeleteOpts, "buffer"> | undefined): void; + }; + }; + keys: { + /** + * Send a key sequence to the browser, simulating physical key presses. + * + * The key sequence can include multiple regular keys, special keys, and modifiers. + * + * For example: + * + * ```ts + * // Send a simple key sequence, each char is sent separately + * await glide.keys.send("hello"); + * + * // Send with modifiers, results in two events + * // - { ctrlKey: true, key: 'a' } + * // - { ctrlKey: true, key: 'c' } + * await glide.keys.send("<C-a><C-c>"); + * ``` + */ + send<const Keys>(keyseq: $keymapcompletions.T<Keys> | { + glide_key: string; + }, opts?: glide.KeySendOptions): Promise<void>; + /** + * Returns a `Promise` that resolves to a {@link glide.KeyEvent} when the next key is pressed. + * + * This also prevents the key input from being processed further and does *not* invoke any associated mappings. + * + * If you *want* to inspect keys without preventing any default behaviour, you can use {@link glide.keys.next_passthrough}. + * + * Note: there can only be one `Promise` registered at any given time. + * + * Note: this does not include modifier keys by themselves, e.g. just pressing ctrl will not resolve + * until another key is pressed, e.g. `<C-a>`. + */ + next(): Promise<glide.KeyEvent>; + /** + * Returns a `Promise` that resolves to a {@link glide.KeyEvent} when the next key is pressed. + * + * Unlike {@link glide.keys.next}, this does not prevent key events from passing through into their original behaviour. + * + * Note: this does not include modifier keys by themselves, e.g. just pressing ctrl will not resolve + * until another key is pressed, e.g. `<C-a>`. + */ + next_passthrough(): Promise<glide.KeyEvent>; + /** + * Returns a `Promise` that resolves to a string representation of the key, when the next key is pressed. + * + * This also prevents the key input from being processed further and does *not* invoke any associated mappings. + * + * If you *want* to inspect keys without preventing any default behaviour, you can use {@link glide.keys.next_passthrough}. + * + * Note: there can only be one `Promise` registered at any given time. + * + * Note: this does not include modifier keys by themselves, e.g. just pressing ctrl will not resolve + * until another key is pressed, e.g. `<C-a>`. + * + * @example 'd' + * @example '<C-l>' + */ + next_str(): Promise<string>; + /** + * Parse a single key notation into a structured object. + * + * This normalises special keys to be consistent but otherwise the + * parsed object only containers modifiers that were in the input string. + * + * Shifted keys are *not* special cased, the returned key is whatever was given + * in in the input. + * + * @example "<Space>" -> { key: "<Space>" } + * @example "H" -> { key: "H" } + * @example "<S-h>" -> { key: "h", shift: true } + * @example "<S-H>" -> { key: "H", shift: true } + * @example "<C-S-a>" -> { key: "A", shift: true, ctrl: true } + * @example "<M-a>" -> { key: "a", meta: true } + */ + parse(key_notation: string): glide.KeyNotation; + }; + unstable: { + /** + * Include another file as part of your config. The given file is evluated as if it + * was just another Glide config file. + * + * **note**: this only supports files that are directly relative to your config file, + * for example, `ts:"shared.glide.ts"` or `ts:"shared/glide.ts"` would work but + * `ts:"../shared/glide.ts"` will not. + * + * **note**: this function cannot be called from inside a file that has been included + * itself, i.e. nested {@link glide.unstable.include} calls are not supported. + * + * @example glide.unstable.include("shared.glide.ts") + */ + include(path: string): Promise<void>; + }; + path: { + readonly cwd: string; + readonly home_dir: string; + readonly temp_dir: string; + readonly profile_dir: string; + /** + * Join all arguments together and normalize the resulting path. + * + * Throws an error on non-relative paths. + */ + join(...parts: string[]): string; + }; + fs: { + /** + * Read the file at the given path. + * + * Relative paths are resolved relative to the config directory, if no config directory is defined then relative + * paths are not allowed. + * + * The `encoding` must currently be set to `"utf8"` as that is the only supported encoding. + * + * @example await glide.fs.read("github.css", "utf8"); + */ + read(path: string, encoding: "utf8"): Promise<string>; + /** + * Write to the file at the given path. + * + * Relative paths are resolved relative to the config directory, if no config directory is defined then relative + * paths are not allowed. + * + * If the path has parent directories that do not exist, they will be created. + * + * The `contents` are written in utf8. + * + * @example await glide.fs.write("github.css", ".copilot { display: none !important }"); + */ + write(path: string, contents: string): Promise<void>; + /** + * Determine if the given path exists. + * + * Relative paths are resolved relative to the config directory, if no config directory is defined then relative + * paths are not allowed. + * + * @example await glide.fs.exists(`${glide.path.home_dir}/.config/foo`); + */ + exists(path: string): Promise<boolean>; + /** + * Obtain information about a file, such as size, modification dates, etc. + * + * Relative paths are resolved relative to the config directory, if no config directory is defined then relative + * paths are not allowed. + * + * ```ts + * const stat = await glide.fs.stat('userChrome.css'); + * stat.last_modified // 1758835015092 + * stat.type // "file" + * ``` + */ + stat(path: string): Promise<glide.FileInfo>; + }; + messengers: { + /** + * Create a {@link glide.ParentMessenger} that can be used to communicate with the content process. + * + * Communication is currently uni-directional, the content process can communicate with the main + * process, but not the other way around. + * + * Sending and receiving messages is type safe & determined from the type variable passed to this function. + * e.g. in the example below, the only message that can be sent is `my_message`. + * + * ```typescript + * // create a messenger and pass in the callback that will be invoked + * // when `messenger.send()` is called below + * const messenger = glide.messengers.create<{ my_message: null }>((message) => { + * switch (message.name) { + * case "my_message": { + * // ... + * break; + * } + * } + * }); + * + * glide.keymaps.set("normal", "gt", ({ tab_id }) => { + * // note the `messenger.content.execute()` function intead of + * // the typical `glide.content.execute()` function. + * messenger.content.execute((messenger) => { + * document.addEventListener('focusin', (event) => { + * if (event.target.id === 'my-element') { + * messenger.send('my_message'); + * } + * }) + * }, { tab_id }); + * }); + * ``` + */ + create<Messages extends Record<string, any>>(receiver: (message: glide.Message<Messages>) => void): glide.ParentMessenger<Messages>; + }; + modes: { + /** + * Register a custom `mode`. + * + * **note**: you must *also* register it as a type like so: + * + * ```typescript + * declare global { + * interface GlideModes { + * leap: "leap"; + * } + * } + * glide.modes.register('leap', { caret: 'block' }) + * ``` + */ + register<Mode extends keyof GlideModes>(mode: Mode, opts: { + caret: "block" | "line" | "underline"; + }): void; + }; + }; + /** + * Defines all the supported modes. + * + * **note**: the key is what defines the list of supported modes, currently the value is + * not used for anything. + * + * **note**: you must *also* register it at runtime like so: + * + * ```typescript + * declare global { + * interface GlideModes { + * leap: "leap"; + * } + * } + * glide.modes.register('leap', { caret: 'block' }) + * ``` + */ + interface GlideModes { + normal: "normal"; + insert: "insert"; + visual: "visual"; + ignore: "ignore"; + command: "command"; + "op-pending": "op-pending"; + } + /** + * All of the supported modes. + * + * See {@link GlideModes} for more information. + */ + type GlideMode = keyof GlideModes; + interface GlideGlobals { + /** + * The key notation that any `<leader>` mapping matches against. + * + * For example, a mapping defined with `<leader>r` would be matched when Space + r is pressed. + * + * @default "<Space>" + */ + mapleader: string; + } + /** + * Throws an error if the given value is not truthy. + * + * Returns the value if it is truthy. + */ + function ensure<T>(value: T, message?: string): T extends false | "" | 0 | 0n | null | undefined ? never : T; + /** + * Assert an invariant. An \`AssertionError\` will be thrown if `value` is falsy. + */ + function assert(value: unknown, message?: string): asserts value; + /** + * The inverse of `{@link assert}`, useful for blowing up when the condition becomes `truthy`. + */ + function todo_assert(value: unknown, message?: string): void; + /** + * Helper function for asserting exhaustiveness checks. + * + * You can optionally pass a second argument which will be used as the error message, + * if not given then the first argument will be stringified in the error message. + * + * ```typescript + * switch (union.type) { + * case 'type1': ... + * case 'type2': ... + * default: + * throw assert_never(union.type); + * } + */ + function assert_never(x: never, detail?: string | Error): never; + class FileNotFoundError extends Error { + path: string; + constructor(message: string, props: { + path: string; + }); + } + class GlideProcessError extends Error { + process: glide.CompletedProcess; + exit_code: number; + constructor(message: string, process: glide.CompletedProcess); + } + /** + * Interface used to define types for excmds, intended for declaration merging. + * + * e.g. + * ```typescript + * const cmd = glide.excmds.create( + * { name: "my_excmd", description: "..." }, + * () => { + * // ... + * } + * ); + * declare global { + * interface ExcmdRegistry { + * my_excmd: typeof cmd; + * } + * } + * ``` + */ + export interface ExcmdRegistry { + } + namespace glide { + /** + * Corresponds to {@link glide.o} or {@link glide.bo}. + */ + // note: this is skipped in docs generation because we expand `glide.o`, so rendering + // the `Options` type as well would be redundant. + /// @docs-skip + export type Options = { + /** + * How long to wait until cancelling a partial keymapping execution. + * + * For example, `glide.keymaps.set('insert', 'jj', 'mode_change normal')`, after + * pressing `j` once, this option determines how long the delay should be until + * the `j` key is considered fully pressed and the mapping sequence is reset. + * + * note: this only applies in insert mode. + * + * @default 200 + */ + mapping_timeout: number; + /** + * Color used to briefly highlight text when it's yanked. + * + * @example "#ff6b35" // Orange highlight + * @default "#edc73b" + */ + yank_highlight: glide.RGBString; + /** + * How long, in milliseconds, to highlight the selection for when it's yanked. + * + * @default 150 + */ + yank_highlight_time: number; + /** + * The delay, in milliseconds, before showing the which key UI. + * + * @default 300 + */ + which_key_delay: number; + /** + * The maximum number of entries to include in the jumplist, i.e. + * how far back in history will the jumplist store. + * + * @default 100 + */ + jumplist_max_entries: number; + /** + * The font size of the hint label, directly corresponds to the + * [font-size](https://developer.mozilla.org/en-US/docs/Web/CSS/font-size) property. + * + * @default "11px" + */ + hint_size: string; + }; + export type SpawnOptions = { + cwd?: string; + env?: Record<string, string | null>; + extend_env?: boolean; + success_codes?: number[]; + /** + * If `false`, do not throw an error for non-zero exit codes. + * + * @default true + */ + check_exit_code?: boolean; + /** + * Control where the stderr output is sent. + * + * If `"pipe"` then sterr is accessible through `process.stderr`. + * If `"stdout"` then sterr is mixed with stdout and accessible through `process.stdout`. + * + * @default "pipe" + */ + stderr?: "pipe" | "stdout"; + }; + export type Process = { + pid: number; + /** + * The process exit code. + * + * `null` if it has not exited yet. + */ + exit_code: number | null; + /** + * A `ReadableStream` of `string`s from the stdout pipe. + */ + stdout: ReadableStream<string>; + /** + * A `ReadableStream` of `string`s from the stderr pipe. + * + * This is `null` if the `stderr: 'stdout'` option was set as the pipe will be forwarded + * to `stdout` instead. + */ + stderr: ReadableStream<string> | null; + /** + * Wait for the process to exit. + */ + wait(): Promise<glide.CompletedProcess>; + /** + * Kill the process. + * + * On platforms which support it, the process will be sent a `SIGTERM` signal immediately, + * so that it has a chance to terminate gracefully, and a `SIGKILL` signal if it hasn't exited + * within `timeout` milliseconds. + * + * @param {integer} [timeout=300] + * A timeout, in milliseconds, after which the process will be forcibly killed. + */ + kill(timeout?: number): Promise<glide.CompletedProcess>; + }; + /** + * Represents a process that has exited. + */ + export type CompletedProcess = glide.Process & { + exit_code: number; + }; + export type RGBString = `#${string}`; + /** A web extension tab that is guaranteed to have the `ts:id` property present. */ + export type TabWithID = Omit<Browser.Tabs.Tab, "id"> & { + id: number; + }; + export type KeyEvent = KeyboardEvent & { + /** + * The vim notation of the KeyEvent, e.g. + * + * `{ ctrlKey: true, key: 's' }` -> `'<C-s>'` + */ + glide_key: string; + }; + export type KeySendOptions = { + /** + * Send the key event(s) directly through to the builtin Firefox + * input handler and skip all of the mappings defined in Glide. + */ + skip_mappings?: boolean; + }; + export type KeymapCallback = (props: glide.KeymapCallbackProps) => void; + export type KeymapCallbackProps = { + /** + * The tab that the callback is being executed in. + */ + tab_id: number; + }; + /// @docs-skip + export type ExcmdCreateProps = { + name: string; + description?: string | undefined; + }; + /// @docs-skip + export type ExcmdValue = glide.ExcmdString | glide.ExcmdCallback | glide.KeymapCallback; + /// @docs-skip + export type ExcmdCallback = (props: glide.ExcmdCallbackProps) => void; + /// @docs-skip + export type ExcmdCallbackProps = { + /** + * The tab that the callback is being executed in. + */ + tab_id: number; + /** + * The args passed to the excmd. + * + * @example "foo -r" -> ["-r"] + * @example "foo -r 'string with spaces'" -> ["-r", "string with spaces"] + */ + args_arr: string[]; + }; + /// @docs-skip + export type ExcmdString = + // builtin + GlideCommandString + // custom + | keyof ExcmdRegistry | `${keyof ExcmdRegistry} ${string}`; + /// @docs-skip + export type ContentHint = { + id: number; + x: number; + y: number; + width: number; + height: number; + element: HTMLElement; + }; + export type HintLocation = "content" | "browser-ui"; + export type KeyNotation = { + /** + * @example <leader> + * @example h + * @example j + * @example K + * @example L + * @example <Tab> + */ + key: string; + // modifiers + alt: boolean; + ctrl: boolean; + meta: boolean; + shift: boolean; + }; + export type Keymap = { + sequence: string[]; + lhs: string; + rhs: glide.ExcmdValue; + description: string | undefined; + mode: GlideMode; + }; + export type KeymapOpts = { + description?: string | undefined; + /** + * If `true`, applies the mapping for the current buffer instead of globally. + * + * @default {false} + */ + buffer?: boolean; + /** + * If true, the key sequence will be displayed even after the mapping is executed. + * + * This is useful for mappings that are conceptually chained but are not *actually*, e.g. `diw`. + * + * @default false + */ + retain_key_display?: boolean; + }; + export type KeymapDeleteOpts = Pick<glide.KeymapOpts, "buffer">; + type AutocmdEvent = "UrlEnter" | "ModeChanged" | "ConfigLoaded" | "WindowLoaded" | "KeyStateChanged"; + type AutocmdPatterns = { + UrlEnter: RegExp | { + hostname?: string; + }; + ModeChanged: "*" | `${GlideMode | "*"}:${GlideMode | "*"}`; + ConfigLoaded: null; + WindowLoaded: null; + KeyStateChanged: null; + }; + type AutocmdArgs = { + UrlEnter: { + readonly url: string; + readonly tab_id: number; + }; + ModeChanged: { + /** + * This may be `null` when first loading Glide or when reloading the config. + */ + readonly old_mode: GlideMode | null; + readonly new_mode: GlideMode; + }; + ConfigLoaded: {}; + WindowLoaded: {}; + KeyStateChanged: { + readonly mode: GlideMode; + readonly sequence: string[]; + readonly partial: boolean; + }; + }; + /// doesn't render properly right now + /// @docs-skip + type Message<Messages extends Record<string, any>> = { + [K in keyof Messages]: { + name: K; + data: Messages[K]; + }; + }[keyof Messages]; + interface ParentMessenger<Messages extends Record<string, any>> { + content: { + /** + * The given callback is executed in the content process and is given a + * {@link glide.ContentMessenger} as the first argument. + * + * **note**: unlike {@link glide.content.execute} the callback cannot be passed custom arguments + */ + execute: (callback: (messenger: glide.ContentMessenger<Messages>) => void, opts: { + /** + * The ID of the tab into which to inject. + * + * Or the tab object as returned by {@link glide.tabs.active}. + */ + tab_id: number | glide.TabWithID; + }) => void; + }; + } + interface ContentMessenger<Messages extends Record<string, any>> { + /** + * Send a message to the receiver in the parent process. + */ + send<MessageName extends keyof Messages>(name: MessageName): void; + } + export type FileInfo = { + type: "file" | "directory" | null; + permissions: number | undefined; + last_accessed: number | undefined; + last_modified: number | undefined; + creation_time: number | undefined; + path: string | undefined; + size: number | undefined; + }; + } + /** + * Dedent template function. + * + * Inspired by the https://www.npmjs.com/package/dedent package. + */ + function dedent(arg: string): string; + function dedent(strings: TemplateStringsArray, ...values: unknown[]): string; + /** + * Dedent template function for syntax highlighting. + * + * Inspired by the https://www.npmjs.com/package/dedent package. + * + * note: we don't support passing in arguments to these functions as we would have to + * support escaping them, to not make it easy to accidentally cause XSS + */ + function html(arg: TemplateStringsArray): string; + /** + * Dedent template function for syntax highlighting. + * + * Inspired by the https://www.npmjs.com/package/dedent package. + * + * note: we don't support passing in arguments to these functions as we would have to + * support escaping them, to not make it easy to accidentally cause XSS + */ + function css(arg: TemplateStringsArray): string; + /** + * Helper functions for interacting with the DOM. + * + * **note**: this is currently only available in the main process, for + * updating the browser UI itself. it is not available in + * content processes. + */ + var DOM: { + /** + * Wrapper over `document.createElement()` providing a more ergonomic API. + * + * Element properties that can be assigned directly can be provided as props: + * + * ```ts + * DOM.create_element('img', { src: '...' }); + * ``` + * + * You can also pass a `children` property, which will use `.replaceChildren()`: + * + * ```ts + * DOM.create_element("div", { + * children: ["text content", DOM.create_element("img", { alt: "hint" })], + * }); + * ``` + */ + create_element<TagName extends keyof HTMLElementTagNameMap | (string & {})>(tag_name: TagName, props?: DOM.CreateElementProps<TagName extends keyof HTMLElementTagNameMap ? TagName : "div">): TagName extends keyof HTMLElementTagNameMap ? HTMLElementTagNameMap[TagName] : HTMLElement; + }; + namespace DOM { + type Utils = typeof DOM; + type CreateElementProps<K extends keyof HTMLElementTagNameMap> = Omit<Partial<NonReadonly<HTMLElementTagNameMap[K]>>, "children"> & { + /** + * Can be an individual child or an array of children. + */ + children?: (Node | string) | Array<Node | string>; + /** + * Set arbitrary attributes on the element. + */ + attributes?: Record<string, string>; + /** + * Set specific CSS style properties. + * + * This uses the JS style naming convention for properties, e.g. `zIndex`. + */ + style?: Partial<CSSStyleDeclaration>; + }; + } + namespace $keymapcompletions { + /** + * This type takes in a string literal type, e.g. `<C-`, `a`, `<leader>` + * and resolves a new string literal type union type that represents as many + * valid additional entries as possible. + * + * `<C-` -> `<C-a>` | `<C-D-` ... + * `<leader>` -> `<leader>f` | `<leader><CR>` ... + * `g` -> `gg` | `gj` ... + */ + type T<LHS> = LHS extends "" ? SingleKey : LHS extends "<" ? SpecialKey | `<${ModifierKey}-` : LHS extends `${infer S}<${infer M}-` ? `${S}<${M}-${Exclude<StripAngles<SingleKey>, ModifierKey>}>` | `${S}<${M}-${ModifierKey}-` | (S & {}) : LHS extends `${infer S}<` ? `${S}${SpecialKey}` | S : LHS extends `${infer S}` ? `${S}${SingleKey}` | S : LHS; + /** + * e.g. a, b, <leader> + */ + type SingleKey = StringToUnion<"abcdefghijklmnoprstuvwxyz"> | StringToUnion<"ABCDEFGHIJKLMNOPRSTUVWXYZ"> | StringToUnion<"0123456789"> | SpecialKey; + type SpecialKey = "<space>" | "<tab>" | "<esc>" | "<escape>" | "<space>" | "<enter>" | "<backspace>" | "<BS>" | "<CR>" | "<leader>" | "<up>" | "<down>" | "<left>" | "<right>" | "<del>" | "<home>" | "<end>" | "<pageup>" | "<pagedown>" | "<F1>" | "<F2>" | "<F3>" | "<F4>" | "<F5>" | "<F6>" | "<F7>" | "<F8>" | "<F9>" | "<F10>" | "<F11>" | "<F12>" | "<lt>" | "<bar>" | "<bslash>"; + type ModifierKey = "C" | "D" | "A" | "S"; + type StringToUnion<S extends string> = S extends `${infer First}${infer Rest}` ? First | StringToUnion<Rest> : never; + /** + * `<foo>` -> `foo` + */ + type StripAngles<K extends SingleKey> = K extends `<${infer Inner}>` ? Inner : K; + } +} +/// ----------------- util types ----------------- +/** + * Filter out `readonly` properties from the given object type. + */ +export type NonReadonly<T> = Pick<T, { + [K in keyof T]: T[K] extends Readonly<any> ? never : K; +}[keyof T]>; +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +////////////////////////////////////////////////////// +// BEWARE: DO NOT EDIT MANUALLY! Changes will be lost! +////////////////////////////////////////////////////// +declare global { + const browser: Browser.Browser; + namespace Browser { + /** + * Namespace: browser.activityLog + */ + namespace ActivityLog { + interface OnExtensionActivityDetailsType { + /** + * The date string when this call is triggered. + */ + timeStamp: ExtensionTypes.DateType; + /** + * The type of log entry. api_call is a function call made by the extension and api_event is an event callback to the + * extension. content_script is logged when a content script is injected. + */ + type: OnExtensionActivityDetailsTypeTypeEnum; + /** + * The type of view where the activity occurred. Content scripts will not have a viewType. + * Optional. + */ + viewType?: OnExtensionActivityDetailsTypeViewTypeEnum; + /** + * The name of the api call or event, or the script url if this is a content or user script event. + */ + name: string; + data: OnExtensionActivityDetailsTypeDataType; + } + /** + * The type of log entry. api_call is a function call made by the extension and api_event is an event callback to the + * extension. content_script is logged when a content script is injected. + */ + type OnExtensionActivityDetailsTypeTypeEnum = "api_call" | "api_event" | "content_script" | "user_script"; + /** + * The type of view where the activity occurred. Content scripts will not have a viewType. + */ + type OnExtensionActivityDetailsTypeViewTypeEnum = "background" | "popup" | "sidebar" | "tab" | "devtools_page" | "devtools_panel"; + /** + * The result of the call. + */ + interface OnExtensionActivityDetailsTypeDataResultType { + [s: string]: unknown; + } + interface OnExtensionActivityDetailsTypeDataType { + /** + * A list of arguments passed to the call. + * Optional. + */ + args?: unknown[]; + /** + * The result of the call. + * Optional. + */ + result?: OnExtensionActivityDetailsTypeDataResultType; + /** + * The tab associated with this event if it is a tab or content script. + * Optional. + */ + tabId?: number; + /** + * If the type is content_script, this is the url of the script that was injected. + * Optional. + */ + url?: string; + } + /** + * Receives an activityItem for each logging event. + */ + interface OnExtensionActivityEvent extends Events.Event<(details: OnExtensionActivityDetailsType) => void> { + /** + * Registers an event listener <em>callback</em> to an event. + * + * @param callback Called when an event occurs. The parameters of this function depend on the type of event. + */ + addListener(callback: (details: OnExtensionActivityDetailsType) => void, id: string): void; + } + interface Static { + /** + * Receives an activityItem for each logging event. + */ + onExtensionActivity: OnExtensionActivityEvent; + } + } + /** + * Namespace: browser.alarms + */ + namespace Alarms { + interface Alarm { + /** + * Name of this alarm. + */ + name: string; + /** + * Time when the alarm is scheduled to fire, in milliseconds past the epoch. + */ + scheduledTime: number; + /** + * When present, signals that the alarm triggers periodically after so many minutes. + * Optional. + */ + periodInMinutes?: number; + } + /** + * Details about the alarm. The alarm first fires either at 'when' milliseconds past the epoch (if 'when' is provided), + * after 'delayInMinutes' minutes from the current time (if 'delayInMinutes' is provided instead), + * or after 'periodInMinutes' minutes from the current time (if only 'periodInMinutes' is provided). + * Users should never provide both 'when' and 'delayInMinutes'. If 'periodInMinutes' is provided, + * then the alarm recurs repeatedly after that many minutes. + */ + interface CreateAlarmInfoType { + /** + * Time when the alarm is scheduled to first fire, in milliseconds past the epoch. + * Optional. + */ + when?: number; + /** + * Number of minutes from the current time after which the alarm should first fire. + * Optional. + */ + delayInMinutes?: number; + /** + * Number of minutes after which the alarm should recur repeatedly. + * Optional. + */ + periodInMinutes?: number; + } + interface Static { + /** + * Creates an alarm. After the delay is expired, the onAlarm event is fired. If there is another alarm with the same name + * (or no name if none is specified), it will be cancelled and replaced by this alarm. + * + * @param name Optional. Optional name to identify this alarm. Defaults to the empty string. + * @param alarmInfo Details about the alarm. The alarm first fires either at 'when' milliseconds past the epoch (if 'when' + * is provided), after 'delayInMinutes' minutes from the current time (if 'delayInMinutes' is provided instead), + * or after 'periodInMinutes' minutes from the current time (if only 'periodInMinutes' is provided). + * Users should never provide both 'when' and 'delayInMinutes'. If 'periodInMinutes' is provided, + * then the alarm recurs repeatedly after that many minutes. + */ + create(name: string | undefined, alarmInfo: CreateAlarmInfoType): Promise<void>; + /** + * Creates an alarm. After the delay is expired, the onAlarm event is fired. If there is another alarm with the same name + * (or no name if none is specified), it will be cancelled and replaced by this alarm. + * + * @param alarmInfo Details about the alarm. The alarm first fires either at 'when' milliseconds past the epoch (if 'when' + * is provided), after 'delayInMinutes' minutes from the current time (if 'delayInMinutes' is provided instead), + * or after 'periodInMinutes' minutes from the current time (if only 'periodInMinutes' is provided). + * Users should never provide both 'when' and 'delayInMinutes'. If 'periodInMinutes' is provided, + * then the alarm recurs repeatedly after that many minutes. + */ + create(alarmInfo: CreateAlarmInfoType): Promise<void>; + /** + * Retrieves details about the specified alarm. + * + * @param name Optional. The name of the alarm to get. Defaults to the empty string. + */ + get(name?: string): Promise<Alarm | undefined>; + /** + * Gets an array of all the alarms. + */ + getAll(): Promise<Alarm[]>; + /** + * Clears the alarm with the given name. + * + * @param name Optional. The name of the alarm to clear. Defaults to the empty string. + */ + clear(name?: string): Promise<boolean>; + /** + * Clears all alarms. + */ + clearAll(): Promise<boolean>; + /** + * Fired when an alarm has expired. Useful for transient background pages. + * + * @param name The alarm that has expired. + */ + onAlarm: Events.Event<(name: Alarm) => void>; + } + } + /** + * Namespace: browser.bookmarks + */ + namespace Bookmarks { + /** + * Indicates the reason why this node is unmodifiable. The <var>managed</var> value indicates that this node was configured + * by the system administrator or by the custodian of a supervised user. Omitted if the node can be modified by the user + * and the extension (default). + */ + type BookmarkTreeNodeUnmodifiable = "managed"; + /** + * Indicates the type of a BookmarkTreeNode, which can be one of bookmark, folder or separator. + */ + type BookmarkTreeNodeType = "bookmark" | "folder" | "separator"; + /** + * A node (either a bookmark or a folder) in the bookmark tree. Child nodes are ordered within their parent folder. + */ + interface BookmarkTreeNode { + /** + * The unique identifier for the node. IDs are unique within the current profile, and they remain valid even after the + * browser is restarted. + */ + id: string; + /** + * The <code>id</code> of the parent folder. Omitted for the root node. + * Optional. + */ + parentId?: string; + /** + * The 0-based position of this node within its parent folder. + * Optional. + */ + index?: number; + /** + * The URL navigated to when a user clicks the bookmark. Omitted for folders. + * Optional. + */ + url?: string; + /** + * The text displayed for the node. + */ + title: string; + /** + * When this node was created, in milliseconds since the epoch (<code>new Date(dateAdded)</code>). + * Optional. + */ + dateAdded?: number; + /** + * When the contents of this folder last changed, in milliseconds since the epoch. + * Optional. + */ + dateGroupModified?: number; + /** + * Indicates the reason why this node is unmodifiable. The <var>managed</var> value indicates that this node was configured + * by the system administrator or by the custodian of a supervised user. Omitted if the node can be modified by the user + * and the extension (default). + * Optional. + */ + unmodifiable?: BookmarkTreeNodeUnmodifiable; + /** + * Indicates the type of the BookmarkTreeNode, which can be one of bookmark, folder or separator. + * Optional. + */ + type?: BookmarkTreeNodeType; + /** + * An ordered list of children of this node. + * Optional. + */ + children?: BookmarkTreeNode[]; + } + /** + * Object passed to the create() function. + */ + interface CreateDetails { + /** + * Defaults to the Other Bookmarks folder. + * Optional. + */ + parentId?: string; + /** + * Optional. + */ + index?: number; + /** + * Optional. + */ + title?: string; + /** + * Optional. + */ + url?: string; + /** + * Indicates the type of BookmarkTreeNode to create, which can be one of bookmark, folder or separator. + * Optional. + */ + type?: BookmarkTreeNodeType; + } + /** + * An object specifying properties and values to match when searching. Produces bookmarks matching all properties. + */ + interface SearchQueryC2Type { + /** + * A string of words that are matched against bookmark URLs and titles. + * Optional. + */ + query?: string; + /** + * The URL of the bookmark; matches verbatim. Note that folders have no URL. + * Optional. + */ + url?: string; + /** + * The title of the bookmark; matches verbatim. + * Optional. + */ + title?: string; + } + interface MoveDestinationType { + /** + * Optional. + */ + parentId?: string; + /** + * Optional. + */ + index?: number; + } + interface UpdateChangesType { + /** + * Optional. + */ + title?: string; + /** + * Optional. + */ + url?: string; + } + interface OnRemovedRemoveInfoType { + parentId: string; + index: number; + node: BookmarkTreeNode; + } + interface OnChangedChangeInfoType { + title: string; + /** + * Optional. + */ + url?: string; + } + interface OnMovedMoveInfoType { + parentId: string; + index: number; + oldParentId: string; + oldIndex: number; + } + interface Static { + /** + * Retrieves the specified BookmarkTreeNode(s). + * + * @param idOrIdList A single string-valued id, or an array of string-valued ids + */ + get(idOrIdList: string | string[]): Promise<BookmarkTreeNode[]>; + /** + * Retrieves the children of the specified BookmarkTreeNode id. + */ + getChildren(id: string): Promise<BookmarkTreeNode[]>; + /** + * Retrieves the recently added bookmarks. + * + * @param numberOfItems The maximum number of items to return. + */ + getRecent(numberOfItems: number): Promise<BookmarkTreeNode[]>; + /** + * Retrieves the entire Bookmarks hierarchy. + */ + getTree(): Promise<BookmarkTreeNode[]>; + /** + * Retrieves part of the Bookmarks hierarchy, starting at the specified node. + * + * @param id The ID of the root of the subtree to retrieve. + */ + getSubTree(id: string): Promise<BookmarkTreeNode[]>; + /** + * Searches for BookmarkTreeNodes matching the given query. Queries specified with an object produce BookmarkTreeNodes + * matching all specified properties. + * + * @param query Either a string of words that are matched against bookmark URLs and titles, or an object. If an object, + * the properties <code>query</code>, <code>url</code>, and <code>title</code> may be specified and bookmarks matching all + * specified properties will be produced. + */ + search(query: string | SearchQueryC2Type): Promise<BookmarkTreeNode[]>; + /** + * Creates a bookmark or folder under the specified parentId. If url is NULL or missing, it will be a folder. + */ + create(bookmark: CreateDetails): Promise<BookmarkTreeNode>; + /** + * Moves the specified BookmarkTreeNode to the provided location. + */ + move(id: string, destination: MoveDestinationType): Promise<BookmarkTreeNode>; + /** + * Updates the properties of a bookmark or folder. Specify only the properties that you want to change; unspecified + * properties will be left unchanged. <b>Note:</b> Currently, only 'title' and 'url' are supported. + */ + update(id: string, changes: UpdateChangesType): Promise<BookmarkTreeNode>; + /** + * Removes a bookmark or an empty bookmark folder. + */ + remove(id: string): Promise<void>; + /** + * Recursively removes a bookmark folder. + */ + removeTree(id: string): Promise<void>; + /** + * Fired when a bookmark or folder is created. + */ + onCreated: Events.Event<(id: string, bookmark: BookmarkTreeNode) => void>; + /** + * Fired when a bookmark or folder is removed. When a folder is removed recursively, + * a single notification is fired for the folder, and none for its contents. + */ + onRemoved: Events.Event<(id: string, removeInfo: OnRemovedRemoveInfoType) => void>; + /** + * Fired when a bookmark or folder changes. <b>Note:</b> Currently, only title and url changes trigger this. + */ + onChanged: Events.Event<(id: string, changeInfo: OnChangedChangeInfoType) => void>; + /** + * Fired when a bookmark or folder is moved to a different parent folder. + */ + onMoved: Events.Event<(id: string, moveInfo: OnMovedMoveInfoType) => void>; + } + } + /** + * Namespace: browser.action + */ + namespace Action { + /** + * Specifies to which tab or window the value should be set, or from which one it should be retrieved. + * If no tab nor window is specified, the global value is set or retrieved. + */ + interface Details { + /** + * When setting a value, it will be specific to the specified tab, and will automatically reset when the tab navigates. + * When getting, specifies the tab to get the value from; if there is no tab-specific value, + * the window one will be inherited. + * Optional. + */ + tabId?: number; + /** + * When setting a value, it will be specific to the specified window. When getting, specifies the window to get the value + * from; if there is no window-specific value, the global one will be inherited. + * Optional. + */ + windowId?: number; + } + type ColorArray = [ + number, + number, + number, + number + ]; + /** + * Pixel data for an image. Must be an ImageData object (for example, from a <code>canvas</code> element). + */ + interface ImageDataType extends ImageData { + [s: string]: unknown; + } + /** + * An array of four integers in the range [0,255] that make up the RGBA color of the badge. For example, + * opaque red is <code>[255, 0, 0, 255]</code>. Can also be a string with a CSS value, with opaque red being <code> + * #FF0000</code> or <code>#F00</code>. + */ + type ColorValue = string | ColorArray | null; + /** + * Information sent when a browser action is clicked. + */ + interface OnClickData { + /** + * An array of keyboard modifiers that were held while the menu item was clicked. + */ + modifiers: OnClickDataModifiersItemEnum[]; + /** + * An integer value of button by which menu item was clicked. + * Optional. + */ + button?: number; + } + interface SetTitleDetailsType extends Details { + /** + * The string the browser action should display when moused over. + */ + title: string | null; + } + /** + * The collection of user-specified settings relating to an extension's action. + */ + interface GetUserSettingsCallbackUserSettingsType { + /** + * Whether the extension's action icon is visible on browser windows' top-level toolbar (i.e., + * whether the extension has been 'pinned' by the user). + * Optional. + */ + isOnToolbar?: boolean; + } + interface SetIconDetailsType extends Details { + /** + * Either an ImageData object or a dictionary {size -> ImageData} representing icon to be set. + * If the icon is specified as a dictionary, the actual image to be used is chosen depending on screen's pixel density. + * If the number of image pixels that fit into one screen space unit equals <code>scale</code>, then image with size <code> + * scale</code> * 19 will be selected. Initially only scales 1 and 2 will be supported. + * At least one image must be specified. Note that 'details.imageData = foo' is equivalent to 'details. + * imageData = {'19': foo}' + * Optional. + */ + imageData?: ImageDataType | Record<string, ImageDataType>; + /** + * Either a relative image path or a dictionary {size -> relative image path} pointing to icon to be set. + * If the icon is specified as a dictionary, the actual image to be used is chosen depending on screen's pixel density. + * If the number of image pixels that fit into one screen space unit equals <code>scale</code>, then image with size <code> + * scale</code> * 19 will be selected. Initially only scales 1 and 2 will be supported. + * At least one image must be specified. Note that 'details.path = foo' is equivalent to 'details.imageData = {'19': foo}' + * Optional. + */ + path?: string | Record<string, string>; + } + interface SetPopupDetailsType extends Details { + /** + * The html file to show in a popup. If set to the empty string (''), no popup is shown. + */ + popup: string | null; + } + interface SetBadgeTextDetailsType extends Details { + /** + * Any number of characters can be passed, but only about four can fit in the space. + */ + text: string | null; + } + interface SetBadgeBackgroundColorDetailsType extends Details { + color: ColorValue; + } + interface SetBadgeTextColorDetailsType extends Details { + color: ColorValue; + } + /** + * An object with information about the popup to open. + */ + interface OpenPopupOptionsType { + /** + * Defaults to the $(topic:current-window)[current window]. + * Optional. + */ + windowId?: number; + } + type OnClickDataModifiersItemEnum = "Shift" | "Alt" | "Command" | "Ctrl" | "MacCtrl"; + interface Static { + /** + * Sets the title of the browser action. This shows up in the tooltip. + */ + setTitle(details: SetTitleDetailsType): Promise<void>; + /** + * Gets the title of the browser action. + */ + getTitle(details: Details): Promise<string>; + /** + * Returns the user-specified settings relating to an extension's action. + */ + getUserSettings(): Promise<GetUserSettingsCallbackUserSettingsType>; + /** + * Sets the icon for the browser action. The icon can be specified either as the path to an image file or as the pixel data + * from a canvas element, or as dictionary of either one of those. Either the <b>path</b> or the <b>imageData</b> + * property must be specified. + */ + setIcon(details: SetIconDetailsType): Promise<void>; + /** + * Sets the html document to be opened as a popup when the user clicks on the browser action's icon. + */ + setPopup(details: SetPopupDetailsType): Promise<void>; + /** + * Gets the html document set as the popup for this browser action. + */ + getPopup(details: Details): Promise<string>; + /** + * Sets the badge text for the browser action. The badge is displayed on top of the icon. + */ + setBadgeText(details: SetBadgeTextDetailsType): Promise<void>; + /** + * Gets the badge text of the browser action. If no tab nor window is specified is specified, + * the global badge text is returned. + */ + getBadgeText(details: Details): Promise<string>; + /** + * Sets the background color for the badge. + */ + setBadgeBackgroundColor(details: SetBadgeBackgroundColorDetailsType): Promise<void>; + /** + * Gets the background color of the browser action badge. + */ + getBadgeBackgroundColor(details: Details): Promise<ColorArray>; + /** + * Sets the text color for the badge. + */ + setBadgeTextColor(details: SetBadgeTextColorDetailsType): Promise<void>; + /** + * Gets the text color of the browser action badge. + */ + getBadgeTextColor(details: Details): Promise<ColorArray>; + /** + * Enables the browser action for a tab. By default, browser actions are enabled. + * + * @param tabId Optional. The id of the tab for which you want to modify the browser action. + */ + enable(tabId?: number): Promise<void>; + /** + * Disables the browser action for a tab. + * + * @param tabId Optional. The id of the tab for which you want to modify the browser action. + */ + disable(tabId?: number): Promise<void>; + /** + * Checks whether the browser action is enabled. + */ + isEnabled(details: Details): Promise<boolean>; + /** + * Opens the extension popup window in the specified window. + * + * @param options Optional. An object with information about the popup to open. + */ + openPopup(options?: OpenPopupOptionsType): Promise<void>; + /** + * Fired when a browser action icon is clicked. This event will not fire if the browser action has a popup. + * + * @param info Optional. + */ + onClicked: Events.Event<(tab: Browser.Tabs.Tab, info: OnClickData | undefined) => void>; + } + } + /** + * Namespace: browser.browserAction + */ + namespace BrowserAction { + interface Static extends Action.Static { + [s: string]: unknown; + } + } + /** + * Namespace: browser.browserSettings + */ + namespace BrowserSettings { + /** + * How images should be animated in the browser. + */ + type ImageAnimationBehavior = "normal" | "none" | "once"; + /** + * After which mouse event context menus should popup. + */ + type ContextMenuMouseEvent = "mouseup" | "mousedown"; + /** + * Color management mode. + */ + type ColorManagementMode = "off" | "full" | "tagged_only"; + interface Static { + /** + * Allows or disallows pop-up windows from opening in response to user events. + */ + allowPopupsForUserEvents: Browser.Types.Setting; + /** + * Enables or disables the browser cache. + */ + cacheEnabled: Browser.Types.Setting; + /** + * This boolean setting controls whether the selected tab can be closed with a double click. + */ + closeTabsByDoubleClick: Browser.Types.Setting; + /** + * Controls after which mouse event context menus popup. This setting's value is of type ContextMenuMouseEvent, + * which has possible values of <code>mouseup</code> and <code>mousedown</code>. + */ + contextMenuShowEvent: Browser.Types.Setting; + /** + * Returns the value of the overridden home page. Read-only. + */ + homepageOverride: Browser.Types.Setting; + /** + * Controls the behaviour of image animation in the browser. This setting's value is of type ImageAnimationBehavior, + * defaulting to <code>normal</code>. + */ + imageAnimationBehavior: Browser.Types.Setting; + /** + * Returns the value of the overridden new tab page. Read-only. + */ + newTabPageOverride: Browser.Types.Setting; + /** + * Controls where new tabs are opened. `afterCurrent` will open all new tabs next to the current tab, + * `relatedAfterCurrent` will open only related tabs next to the current tab, and `atEnd` will open all tabs at the end of + * the tab strip. The default is `relatedAfterCurrent`. + */ + newTabPosition: Browser.Types.Setting; + /** + * This boolean setting controls whether bookmarks are opened in the current tab or in a new tab. + */ + openBookmarksInNewTabs: Browser.Types.Setting; + /** + * This boolean setting controls whether search results are opened in the current tab or in a new tab. + */ + openSearchResultsInNewTabs: Browser.Types.Setting; + /** + * This boolean setting controls whether urlbar results are opened in the current tab or in a new tab. + */ + openUrlbarResultsInNewTabs: Browser.Types.Setting; + /** + * Disables webAPI notifications. + */ + webNotificationsDisabled: Browser.Types.Setting; + /** + * This setting controls whether the user-chosen colors override the page's colors. + */ + overrideDocumentColors: Browser.Types.Setting; + /** + * This setting controls whether a light or dark color scheme overrides the page's preferred color scheme. + */ + overrideContentColorScheme: Browser.Types.Setting; + /** + * This setting controls whether the document's fonts are used. + */ + useDocumentFonts: Browser.Types.Setting; + /** + * This boolean setting controls whether zoom is applied to the full page or to text only. + */ + zoomFullPage: Browser.Types.Setting; + /** + * This boolean setting controls whether zoom is applied on a per-site basis or to the current tab only. If privacy. + * resistFingerprinting is true, this setting has no effect and zoom is applied to the current tab only. + */ + zoomSiteSpecific: Browser.Types.Setting; + colorManagement: ColorManagement.Static; + } + } + /** + * Namespace: browser.browsingData + */ + namespace BrowsingData { + /** + * Options that determine exactly what data will be removed. + */ + interface RemovalOptions { + /** + * Remove data accumulated on or after this date, represented in milliseconds since the epoch (accessible via the <code> + * getTime</code> method of the JavaScript <code>Date</code> object). If absent, defaults to 0 (which would remove all + * browsing data). + * Optional. + */ + since?: ExtensionTypes.DateType; + /** + * Only remove data associated with these hostnames (only applies to cookies and localStorage). + * Optional. + */ + hostnames?: string[]; + /** + * Only remove data associated with this specific cookieStoreId. + * Optional. + */ + cookieStoreId?: string; + /** + * An object whose properties specify which origin types ought to be cleared. If this object isn't specified, + * it defaults to clearing only "unprotected" origins. Please ensure that you <em>really</em> + * want to remove application data before adding 'protectedWeb' or 'extensions'. + * Optional. + */ + originTypes?: RemovalOptionsOriginTypesType; + } + /** + * A set of data types. Missing data types are interpreted as <code>false</code>. + */ + interface DataTypeSet { + /** + * The browser's cache. Note: when removing data, this clears the <em>entire</em> cache: it is not limited to the range you + * specify. + * Optional. + */ + cache?: boolean; + /** + * The browser's cookies. + * Optional. + */ + cookies?: boolean; + /** + * The browser's download list. + * Optional. + */ + downloads?: boolean; + /** + * The browser's stored form data. + * Optional. + */ + formData?: boolean; + /** + * The browser's history. + * Optional. + */ + history?: boolean; + /** + * Websites' IndexedDB data. + * Optional. + */ + indexedDB?: boolean; + /** + * Websites' local storage data. + * Optional. + */ + localStorage?: boolean; + /** + * Server-bound certificates. + * Optional. + */ + serverBoundCertificates?: boolean; + /** + * Stored passwords. + * Optional. + */ + passwords?: boolean; + /** + * Plugins' data. + * Optional. + */ + pluginData?: boolean; + /** + * Service Workers. + * Optional. + */ + serviceWorkers?: boolean; + } + interface SettingsCallbackResultType { + options: RemovalOptions; + /** + * All of the types will be present in the result, with values of <code>true</code> if they are both selected to be removed + * and permitted to be removed, otherwise <code>false</code>. + */ + dataToRemove: DataTypeSet; + /** + * All of the types will be present in the result, with values of <code>true</code> if they are permitted to be removed (e. + * g., by enterprise policy) and <code>false</code> if not. + */ + dataRemovalPermitted: DataTypeSet; + } + /** + * An object whose properties specify which origin types ought to be cleared. If this object isn't specified, + * it defaults to clearing only "unprotected" origins. Please ensure that you <em>really</em> + * want to remove application data before adding 'protectedWeb' or 'extensions'. + */ + interface RemovalOptionsOriginTypesType { + /** + * Normal websites. + * Optional. + */ + unprotectedWeb?: boolean; + /** + * Websites that have been installed as hosted applications (be careful!). + * Optional. + */ + protectedWeb?: boolean; + /** + * Extensions and packaged applications a user has installed (be _really_ careful!). + * Optional. + */ + extension?: boolean; + } + interface Static { + /** + * Reports which types of data are currently selected in the 'Clear browsing data' settings UI. + * Note: some of the data types included in this API are not available in the settings UI, + * and some UI settings control more than one data type listed here. + */ + settings(): Promise<SettingsCallbackResultType>; + /** + * Clears various types of browsing data stored in a user's profile. + * + * @param dataToRemove The set of data types to remove. + * @returns Called when deletion has completed. + */ + remove(options: RemovalOptions, dataToRemove: DataTypeSet): Promise<void>; + /** + * Clears the browser's cache. + * + * @returns Called when the browser's cache has been cleared. + */ + removeCache(options: RemovalOptions): Promise<void>; + /** + * Clears the browser's cookies and server-bound certificates modified within a particular timeframe. + * + * @returns Called when the browser's cookies and server-bound certificates have been cleared. + */ + removeCookies(options: RemovalOptions): Promise<void>; + /** + * Clears the browser's list of downloaded files (<em>not</em> the downloaded files themselves). + * + * @returns Called when the browser's list of downloaded files has been cleared. + */ + removeDownloads(options: RemovalOptions): Promise<void>; + /** + * Clears the browser's stored form data (autofill). + * + * @returns Called when the browser's form data has been cleared. + */ + removeFormData(options: RemovalOptions): Promise<void>; + /** + * Clears the browser's history. + * + * @returns Called when the browser's history has cleared. + */ + removeHistory(options: RemovalOptions): Promise<void>; + /** + * Clears websites' local storage data. + * + * @returns Called when websites' local storage has been cleared. + */ + removeLocalStorage(options: RemovalOptions): Promise<void>; + /** + * Clears plugins' data. + * + * @returns Called when plugins' data has been cleared. + */ + removePluginData(options: RemovalOptions): Promise<void>; + /** + * Clears the browser's stored passwords. + * + * @returns Called when the browser's passwords have been cleared. + */ + removePasswords(options: RemovalOptions): Promise<void>; + } + } + /** + * Namespace: browser.captivePortal + */ + namespace CaptivePortal { + interface OnStateChangedDetailsType { + /** + * The current captive portal state. + */ + state: OnStateChangedDetailsTypeStateEnum; + } + type OnConnectivityAvailableStatusEnum = "captive" | "clear"; + /** + * The current captive portal state. + */ + type OnStateChangedDetailsTypeStateEnum = "unknown" | "not_captive" | "unlocked_portal" | "locked_portal"; + interface Static { + /** + * Returns the current portal state, one of `unknown`, `not_captive`, `unlocked_portal`, `locked_portal`. + */ + getState(): Promise<"unknown" | "not_captive" | "unlocked_portal" | "locked_portal">; + /** + * Returns the time difference between NOW and the last time a request was completed in milliseconds. + */ + getLastChecked(): Promise<number>; + /** + * Fired when the captive portal state changes. + */ + onStateChanged: Events.Event<(details: OnStateChangedDetailsType) => void>; + /** + * This notification will be emitted when the captive portal service has determined that we can connect to the internet. + * The service will pass either `captive` if there is an unlocked captive portal present, + * or `clear` if no captive portal was detected. + */ + onConnectivityAvailable: Events.Event<(status: OnConnectivityAvailableStatusEnum) => void>; + /** + * Return the canonical captive-portal detection URL. Read-only. + */ + canonicalURL: Browser.Types.Setting; + } + } + /** + * Namespace: browser.clipboard + */ + namespace Clipboard { + /** + * The type of imageData. + */ + type SetImageDataImageTypeEnum = "jpeg" | "png"; + interface Static { + /** + * Copy an image to the clipboard. The image is re-encoded before it is written to the clipboard. If the image is invalid, + * the clipboard is not modified. + * + * @param imageData The image data to be copied. + * @param imageType The type of imageData. + */ + setImageData(imageData: ArrayBuffer, imageType: SetImageDataImageTypeEnum): Promise<void>; + } + } + /** + * Namespace: browser.commands + */ + namespace Commands { + interface Command { + /** + * The name of the Extension Command + * Optional. + */ + name?: string; + /** + * The Extension Command description + * Optional. + */ + description?: string; + /** + * The shortcut active for this command, or blank if not active. + * Optional. + */ + shortcut?: string; + } + /** + * The new description for the command. + */ + interface UpdateDetailType { + /** + * The name of the command. + */ + name: string; + /** + * The new description for the command. + * Optional. + */ + description?: string; + /** + * Optional. + */ + shortcut?: string; + } + interface OnChangedChangeInfoType { + /** + * The name of the shortcut. + */ + name: string; + /** + * The new shortcut active for this command, or blank if not active. + */ + newShortcut: string; + /** + * The old shortcut which is no longer active for this command, or blank if the shortcut was previously inactive. + */ + oldShortcut: string; + } + interface Static { + /** + * Update the details of an already defined command. + * + * @param detail The new description for the command. + */ + update(detail: UpdateDetailType): Promise<void>; + /** + * Reset a command's details to what is specified in the manifest. + * + * @param name The name of the command. + */ + reset(name: string): Promise<void>; + /** + * Returns all the registered extension commands for this extension and their shortcut (if active). + * + * @returns Called to return the registered commands. + */ + getAll(): Promise<Command[]>; + /** + * Open extension shortcuts configuration page. + */ + openShortcutSettings(): void; + /** + * Fired when a registered command is activated using a keyboard shortcut. + * + * @param tab Optional. Details of the $(ref:tabs.Tab) where the command was activated. + */ + onCommand: Events.Event<(command: string, tab: Browser.Tabs.Tab | undefined) => void>; + /** + * Fired when a registered command's shortcut is changed. + */ + onChanged: Events.Event<(changeInfo: OnChangedChangeInfoType) => void>; + } + } + /** + * Namespace: browser.contentScripts + */ + namespace ContentScripts { + /** + * Details of a content script registered programmatically + */ + interface RegisteredContentScriptOptions { + matches: Browser.Manifest.MatchPattern[]; + /** + * Optional. + */ + excludeMatches?: Browser.Manifest.MatchPattern[]; + /** + * Optional. + */ + includeGlobs?: string[]; + /** + * Optional. + */ + excludeGlobs?: string[]; + /** + * The list of CSS files to inject + * Optional. + */ + css?: Browser.ExtensionTypes.ExtensionFileOrCode[]; + /** + * The list of JS files to inject + * Optional. + */ + js?: Browser.ExtensionTypes.ExtensionFileOrCode[]; + /** + * If allFrames is <code>true</code>, implies that the JavaScript or CSS should be injected into all frames of current page. + * By default, it's <code>false</code> and is only injected into the top frame. + * Optional. + */ + allFrames?: boolean; + /** + * If matchAboutBlank is true, then the code is also injected in about:blank and about:srcdoc frames if your extension has + * access to its parent document. Ignored if matchOriginAsFallback is specified. By default it is <code>false</code>. + * Optional. + */ + matchAboutBlank?: boolean; + /** + * If matchOriginAsFallback is true, then the code is also injected in about:, data:, + * blob: when their origin matches the pattern in 'matches', even if the actual document origin is opaque (due to the use + * of CSP sandbox or iframe sandbox). Match patterns in 'matches' must specify a wildcard path glob. By default it is <code> + * false</code>. + * Optional. + */ + matchOriginAsFallback?: boolean; + /** + * The soonest that the JavaScript or CSS will be injected into the tab. Defaults to "document_idle". + * Optional. + */ + runAt?: Browser.ExtensionTypes.RunAt; + /** + * The JavaScript world for a script to execute within. Defaults to "ISOLATED". + * Optional. + */ + world?: Browser.ExtensionTypes.ExecutionWorld; + /** + * limit the set of matched tabs to those that belong to the given cookie store id + * Optional. + */ + cookieStoreId?: string[] | string; + } + /** + * An object that represents a content script registered programmatically + */ + interface RegisteredContentScript { + /** + * Unregister a content script registered programmatically + */ + unregister(): Promise<void>; + } + interface Static { + /** + * Register a content script programmatically + */ + register(contentScriptOptions: RegisteredContentScriptOptions): Promise<RegisteredContentScript>; + } + } + /** + * Namespace: browser.contextualIdentities + */ + namespace ContextualIdentities { + /** + * Represents information about a contextual identity. + */ + interface ContextualIdentity { + /** + * The name of the contextual identity. + */ + name: string; + /** + * The icon name of the contextual identity. + */ + icon: string; + /** + * The icon url of the contextual identity. + */ + iconUrl: string; + /** + * The color name of the contextual identity. + */ + color: string; + /** + * The color hash of the contextual identity. + */ + colorCode: string; + /** + * The cookie store ID of the contextual identity. + */ + cookieStoreId: string; + } + /** + * Information to filter the contextual identities being retrieved. + */ + interface QueryDetailsType { + /** + * Filters the contextual identity by name. + * Optional. + */ + name?: string; + } + /** + * Details about the contextual identity being created. + */ + interface CreateDetailsType { + /** + * The name of the contextual identity. + */ + name: string; + /** + * The color of the contextual identity. + */ + color: string; + /** + * The icon of the contextual identity. + */ + icon: string; + } + /** + * Details about the contextual identity being created. + */ + interface UpdateDetailsType { + /** + * The name of the contextual identity. + * Optional. + */ + name?: string; + /** + * The color of the contextual identity. + * Optional. + */ + color?: string; + /** + * The icon of the contextual identity. + * Optional. + */ + icon?: string; + } + interface OnUpdatedChangeInfoType { + /** + * Contextual identity that has been updated + */ + contextualIdentity: ContextualIdentity; + } + interface OnCreatedChangeInfoType { + /** + * Contextual identity that has been created + */ + contextualIdentity: ContextualIdentity; + } + interface OnRemovedChangeInfoType { + /** + * Contextual identity that has been removed + */ + contextualIdentity: ContextualIdentity; + } + interface Static { + /** + * Retrieves information about a single contextual identity. + * + * @param cookieStoreId The ID of the contextual identity cookie store. + */ + get(cookieStoreId: string): Promise<ContextualIdentity>; + /** + * Retrieves all contextual identities + * + * @param details Information to filter the contextual identities being retrieved. + */ + query(details: QueryDetailsType): Promise<ContextualIdentity[]>; + /** + * Creates a contextual identity with the given data. + * + * @param details Details about the contextual identity being created. + */ + create(details: CreateDetailsType): Promise<ContextualIdentity>; + /** + * Updates a contextual identity with the given data. + * + * @param cookieStoreId The ID of the contextual identity cookie store. + * @param details Details about the contextual identity being created. + */ + update(cookieStoreId: string, details: UpdateDetailsType): Promise<ContextualIdentity>; + /** + * Reorder one or more contextual identities by their cookieStoreIDs to a given position. + * + * @param cookieStoreIds The ID or list of IDs of the contextual identity cookie stores. + * @param position The position the contextual identity should move to. + */ + move(cookieStoreIds: string | string[], position: number): Promise<void>; + /** + * Deletes a contextual identity by its cookie Store ID. + * + * @param cookieStoreId The ID of the contextual identity cookie store. + */ + remove(cookieStoreId: string): Promise<ContextualIdentity>; + /** + * Fired when a container is updated. + */ + onUpdated: Events.Event<(changeInfo: OnUpdatedChangeInfoType) => void>; + /** + * Fired when a new container is created. + */ + onCreated: Events.Event<(changeInfo: OnCreatedChangeInfoType) => void>; + /** + * Fired when a container is removed. + */ + onRemoved: Events.Event<(changeInfo: OnRemovedChangeInfoType) => void>; + } + } + /** + * Namespace: browser.cookies + */ + namespace Cookies { + /** + * A cookie's 'SameSite' state (https://tools.ietf.org/html/draft-west-first-party-cookies). + * 'no_restriction' corresponds to a cookie set without a 'SameSite' attribute, 'lax' to 'SameSite=Lax', + * and 'strict' to 'SameSite=Strict'. + */ + type SameSiteStatus = "unspecified" | "no_restriction" | "lax" | "strict"; + /** + * The description of the storage partition of a cookie. This object may be omitted (null) if a cookie is not partitioned. + */ + interface PartitionKey { + /** + * The first-party URL of the cookie, if the cookie is in storage partitioned by the top-level site. + * Optional. + */ + topLevelSite?: string; + /** + * Whether or not the cookie is in a third-party context, respecting ancestor chains. + * Optional. + */ + hasCrossSiteAncestor?: boolean; + } + /** + * Represents information about an HTTP cookie. + */ + interface Cookie { + /** + * The name of the cookie. + */ + name: string; + /** + * The value of the cookie. + */ + value: string; + /** + * The domain of the cookie (e.g. "www.google.com", "example.com"). + */ + domain: string; + /** + * True if the cookie is a host-only cookie (i.e. a request's host must exactly match the domain of the cookie). + */ + hostOnly: boolean; + /** + * The path of the cookie. + */ + path: string; + /** + * True if the cookie is marked as Secure (i.e. its scope is limited to secure channels, typically HTTPS). + */ + secure: boolean; + /** + * True if the cookie is marked as HttpOnly (i.e. the cookie is inaccessible to client-side scripts). + */ + httpOnly: boolean; + /** + * The cookie's same-site status (i.e. whether the cookie is sent with cross-site requests). + */ + sameSite: SameSiteStatus; + /** + * True if the cookie is a session cookie, as opposed to a persistent cookie with an expiration date. + */ + session: boolean; + /** + * The expiration date of the cookie as the number of seconds since the UNIX epoch. Not provided for session cookies. + * Optional. + */ + expirationDate?: number; + /** + * The ID of the cookie store containing this cookie, as provided in getAllCookieStores(). + */ + storeId: string; + /** + * The first-party domain of the cookie. + */ + firstPartyDomain: string; + /** + * The cookie's storage partition, if any. null if not partitioned. + * Optional. + */ + partitionKey?: PartitionKey; + } + /** + * Represents a cookie store in the browser. An incognito mode window, for instance, uses a separate cookie store from a + * non-incognito window. + */ + interface CookieStore { + /** + * The unique identifier for the cookie store. + */ + id: string; + /** + * Identifiers of all the browser tabs that share this cookie store. + */ + tabIds: number[]; + /** + * Indicates if this is an incognito cookie store + */ + incognito: boolean; + } + /** + * The underlying reason behind the cookie's change. If a cookie was inserted, or removed via an explicit call to + * $(ref:cookies.remove), "cause" will be "explicit". If a cookie was automatically removed due to expiry, + * "cause" will be "expired". If a cookie was removed due to being overwritten with an already-expired expiration date, + * "cause" will be set to "expired_overwrite". If a cookie was automatically removed due to garbage collection, + * "cause" will be "evicted". If a cookie was automatically removed due to a "set" call that overwrote it, + * "cause" will be "overwrite". Plan your response accordingly. + */ + type OnChangedCause = "evicted" | "expired" | "explicit" | "expired_overwrite" | "overwrite"; + /** + * Details to identify the cookie being retrieved. + */ + interface GetDetailsType { + /** + * The URL with which the cookie to retrieve is associated. This argument may be a full URL, + * in which case any data following the URL path (e.g. the query string) is simply ignored. + * If host permissions for this URL are not specified in the manifest file, the API call will fail. + */ + url: string; + /** + * The name of the cookie to retrieve. + */ + name: string; + /** + * The ID of the cookie store in which to look for the cookie. By default, the current execution context's cookie store + * will be used. + * Optional. + */ + storeId?: string; + /** + * The first-party domain which the cookie to retrieve is associated. This attribute is required if First-Party Isolation + * is enabled. + * Optional. + */ + firstPartyDomain?: string; + /** + * The storage partition, if the cookie is part of partitioned storage. By default, only non-partitioned cookies are + * returned. + * Optional. + */ + partitionKey?: PartitionKey; + } + /** + * Information to filter the cookies being retrieved. + */ + interface GetAllDetailsType { + /** + * Restricts the retrieved cookies to those that would match the given URL. + * Optional. + */ + url?: string; + /** + * Filters the cookies by name. + * Optional. + */ + name?: string; + /** + * Restricts the retrieved cookies to those whose domains match or are subdomains of this one. + * Optional. + */ + domain?: string; + /** + * Restricts the retrieved cookies to those whose path exactly matches this string. + * Optional. + */ + path?: string; + /** + * Filters the cookies by their Secure property. + * Optional. + */ + secure?: boolean; + /** + * Filters out session vs. persistent cookies. + * Optional. + */ + session?: boolean; + /** + * The cookie store to retrieve cookies from. If omitted, the current execution context's cookie store will be used. + * Optional. + */ + storeId?: string; + /** + * Restricts the retrieved cookies to those whose first-party domains match this one. + * This attribute is required if First-Party Isolation is enabled. To not filter by a specific first-party domain, + * use `null` or `undefined`. + * Optional. + */ + firstPartyDomain?: string | null; + /** + * Selects a specific storage partition to look up cookies. Defaults to null, in which case only non-partitioned cookies + * are retrieved. If an object iis passed, partitioned cookies are also included, and filtered based on the keys present in + * the given PartitionKey description. An empty object ({}) returns all cookies (partitioned + unpartitioned), + * a non-empty object (e.g. {topLevelSite: '...'}) only returns cookies whose partition match all given attributes. + * Optional. + */ + partitionKey?: PartitionKey; + } + /** + * Details about the cookie being set. + */ + interface SetDetailsType { + /** + * The request-URI to associate with the setting of the cookie. This value can affect the default domain and path values of + * the created cookie. If host permissions for this URL are not specified in the manifest file, the API call will fail. + */ + url: string; + /** + * The name of the cookie. Empty by default if omitted. + * Optional. + */ + name?: string; + /** + * The value of the cookie. Empty by default if omitted. + * Optional. + */ + value?: string; + /** + * The domain of the cookie. If omitted, the cookie becomes a host-only cookie. + * Optional. + */ + domain?: string; + /** + * The path of the cookie. Defaults to the path portion of the url parameter. + * Optional. + */ + path?: string; + /** + * Whether the cookie should be marked as Secure. Defaults to false. + * Optional. + */ + secure?: boolean; + /** + * Whether the cookie should be marked as HttpOnly. Defaults to false. + * Optional. + */ + httpOnly?: boolean; + /** + * The cookie's same-site status. + * Optional. + */ + sameSite?: SameSiteStatus; + /** + * The expiration date of the cookie as the number of seconds since the UNIX epoch. If omitted, + * the cookie becomes a session cookie. + * Optional. + */ + expirationDate?: number; + /** + * The ID of the cookie store in which to set the cookie. By default, the cookie is set in the current execution context's + * cookie store. + * Optional. + */ + storeId?: string; + /** + * The first-party domain of the cookie. This attribute is required if First-Party Isolation is enabled. + * Optional. + */ + firstPartyDomain?: string; + /** + * The storage partition, if the cookie is part of partitioned storage. By default, non-partitioned storage is used. + * Optional. + */ + partitionKey?: PartitionKey; + } + /** + * Information to identify the cookie to remove. + */ + interface RemoveDetailsType { + /** + * The URL associated with the cookie. If host permissions for this URL are not specified in the manifest file, + * the API call will fail. + */ + url: string; + /** + * The name of the cookie to remove. + */ + name: string; + /** + * The ID of the cookie store to look in for the cookie. If unspecified, the cookie is looked for by default in the current + * execution context's cookie store. + * Optional. + */ + storeId?: string; + /** + * The first-party domain associated with the cookie. This attribute is required if First-Party Isolation is enabled. + * Optional. + */ + firstPartyDomain?: string; + /** + * The storage partition, if the cookie is part of partitioned storage. By default, non-partitioned storage is used. + * Optional. + */ + partitionKey?: PartitionKey; + } + /** + * Contains details about the cookie that's been removed. If removal failed for any reason, this will be "null", + * and $(ref:runtime.lastError) will be set. + */ + interface RemoveCallbackDetailsType { + /** + * The URL associated with the cookie that's been removed. + */ + url: string; + /** + * The name of the cookie that's been removed. + */ + name: string; + /** + * The ID of the cookie store from which the cookie was removed. + */ + storeId: string; + /** + * The first-party domain associated with the cookie that's been removed. + */ + firstPartyDomain: string; + /** + * The storage partition, if the cookie is part of partitioned storage. null if not partitioned. + * Optional. + */ + partitionKey?: PartitionKey; + } + interface OnChangedChangeInfoType { + /** + * True if a cookie was removed. + */ + removed: boolean; + /** + * Information about the cookie that was set or removed. + */ + cookie: Cookie; + /** + * The underlying reason behind the cookie's change. + */ + cause: OnChangedCause; + } + interface Static { + /** + * Retrieves information about a single cookie. If more than one cookie of the same name exists for the given URL, + * the one with the longest path will be returned. For cookies with the same path length, + * the cookie with the earliest creation time will be returned. + * + * @param details Details to identify the cookie being retrieved. + */ + get(details: GetDetailsType): Promise<Cookie | null>; + /** + * Retrieves all cookies from a single cookie store that match the given information. The cookies returned will be sorted, + * with those with the longest path first. If multiple cookies have the same path length, + * those with the earliest creation time will be first. + * + * @param details Information to filter the cookies being retrieved. + */ + getAll(details: GetAllDetailsType): Promise<Cookie[]>; + /** + * Sets a cookie with the given cookie data; may overwrite equivalent cookies if they exist. + * + * @param details Details about the cookie being set. + */ + set(details: SetDetailsType): Promise<Cookie>; + /** + * Deletes a cookie by name. + * + * @param details Information to identify the cookie to remove. + */ + remove(details: RemoveDetailsType): Promise<RemoveCallbackDetailsType | null>; + /** + * Lists all existing cookie stores. + */ + getAllCookieStores(): Promise<CookieStore[]>; + /** + * Fired when a cookie is set or removed. As a special case, note that updating a cookie's properties is implemented as a + * two step process: the cookie to be updated is first removed entirely, generating a notification with "cause" of + * "overwrite" . Afterwards, a new cookie is written with the updated values, generating a second notification with + * "cause" "explicit". + */ + onChanged: Events.Event<(changeInfo: OnChangedChangeInfoType) => void>; + } + } + /** + * Namespace: browser.declarativeContent + */ + namespace DeclarativeContent { + /** + * See <a href="https://developer.mozilla.org/en-US/docs/Web/API/ImageData">https://developer.mozilla. + * org/en-US/docs/Web/API/ImageData</a>. + */ + interface ImageDataType extends ImageData { + [s: string]: unknown; + } + /** + * Matches the state of a web page based on various criteria. + */ + interface PageStateMatcher { + /** + * Matches if the conditions of the <code>UrlFilter</code> are fulfilled for the top-level URL of the page. + * Optional. + */ + pageUrl?: Browser.Events.UrlFilter; + /** + * Matches if all of the CSS selectors in the array match displayed elements in a frame with the same origin as the page's + * main frame. All selectors in this array must be <a href="http://www.w3.org/TR/selectors4/#compound"> + * compound selectors</a> to speed up matching. Note: Listing hundreds of CSS selectors or listing CSS selectors that match + * hundreds of times per page can slow down web sites. + * Optional. + */ + css?: string[]; + /** + * Matches if the bookmarked state of the page is equal to the specified value. Requres the <a + * href='/docs/extensions/develop/concepts/declare-permissions'>bookmarks permission</a>. + * Optional. + */ + isBookmarked?: boolean; + } + /** + * Please use ShowAction. + */ + type ShowPageAction = never; + /** + * A declarative event action that sets the extension's toolbar $(ref:action action) to an enabled state while the + * corresponding conditions are met. This action can be used without <a + * href="/docs/extensions/develop/concepts/declare-permissions#host-permissions">host permissions</a>. + * If the extension has the <a href="/docs/extensions/develop/concepts/activeTab">activeTab</a> permission, + * clicking the page action grants access to the active tab.<p>On pages where the conditions are not met the extension's + * toolbar action will be grey-scale, and clicking it will open the context menu, instead of triggering the action.</p> + */ + interface ShowAction { + [s: string]: unknown; + } + /** + * Declarative event action that sets the n-<abbr title="device-independent pixel">dip</abbr> + * square icon for the extension's $(ref:pageAction page action) or $(ref:browserAction browser action) + * while the corresponding conditions are met. This action can be used without <a + * href="/docs/extensions/develop/concepts/declare-permissions#host-permissions">host permissions</a>, + * but the extension must have a page or browser action.<p>Exactly one of <code>imageData</code> or <code>path</code> + * must be specified. Both are dictionaries mapping a number of pixels to an image representation. + * The image representation in <code>imageData</code> is an <a href="https://developer.mozilla. + * org/en-US/docs/Web/API/ImageData">ImageData</a> object; for example, from a <code>canvas</code> element, + * while the image representation in <code>path</code> is the path to an image file relative to the extension's manifest. + * If <code>scale</code> screen pixels fit into a device-independent pixel, the <code>scale * n</code> icon is used. + * If that scale is missing, another image is resized to the required size.</p> + */ + interface SetIcon { + /** + * Either an <code>ImageData</code> object or a dictionary {size -> ImageData} representing an icon to be set. + * If the icon is specified as a dictionary, the image used is chosen depending on the screen's pixel density. + * If the number of image pixels that fit into one screen space unit equals <code>scale</code>, + * then an image with size <code>scale * n</code> is selected, where <i>n</i> is the size of the icon in the UI. + * At least one image must be specified. Note that <code>details.imageData = foo</code> is equivalent to <code>details. + * imageData = {'16': foo}</code>. + * Optional. + */ + imageData?: ImageDataType | SetIconImageDataC2Type; + } + /** + * Declarative event action that injects a content script. <p><b>WARNING:</b> This action is still experimental and is not + * supported on stable builds of Chrome.</p> + */ + interface RequestContentScript { + /** + * Names of CSS files to be injected as a part of the content script. + * Optional. + */ + css?: string[]; + /** + * Names of JavaScript files to be injected as a part of the content script. + * Optional. + */ + js?: string[]; + /** + * Whether the content script runs in all frames of the matching page, or in only the top frame. Default is <code> + * false</code>. + * Optional. + */ + allFrames?: boolean; + /** + * Whether to insert the content script on <code>about:blank</code> and <code>about:srcdoc</code>. Default is <code> + * false</code>. + * Optional. + */ + matchAboutBlank?: boolean; + } + interface Rule<TCondition, TAction> { + /** + * List of conditions that can trigger the actions. + */ + conditions: TCondition[]; + /** + * List of actions that are triggered if one of the conditions is fulfilled. + */ + actions: TAction[]; + } + /** + * An object which allows the addition and removal of rules for declarative content. + */ + interface RuleEvent<TCondition, TAction> { + /** + * Registers rules to handle events. + * + * @param rules Rules to be registered. These do not replace previously registered rules. + */ + addRules(rules: Array<Rule<TCondition, TAction>>): void; + /** + * Fetches currently registered rules. + * + * @param rules Optional. Rule ids to fetch. + * @param callback Optional. Called when rules have been fetched. + */ + getRules(rules?: string[], callback?: (rules: Array<Rule<TCondition, TAction>>) => void): void; + /** + * Unregisters currently registered rules. + * + * @param rules Optional. Rule ids to be unregistered. + * @param callback Optional. Called when rules were unregistered. + */ + removeRules(rules?: string[], callback?: () => void): void; + } + interface SetIconImageDataC2Type { + [s: string]: unknown; + } + interface Static { + PageStateMatcher: { + new (options?: PageStateMatcher): PageStateMatcher; + }; + ShowAction: { + new (options?: ShowAction): ShowAction; + }; + SetIcon: { + new (options?: SetIcon): SetIcon; + }; + RequestContentScript: { + new (options?: RequestContentScript): RequestContentScript; + }; + onPageChanged: RuleEvent<PageStateMatcher, RequestContentScript | SetIcon | ShowPageAction | ShowAction>; + } + } + /** + * Namespace: browser.declarativeNetRequest + */ + namespace DeclarativeNetRequest { + /** + * How the requested resource will be used. Comparable to the webRequest.ResourceType type. + * object_subrequest is unsupported. + */ + type ResourceType = "main_frame" | "sub_frame" | "stylesheet" | "script" | "image" | "object" | "object_subrequest" | "xmlhttprequest" | "xslt" | "ping" | "beacon" | "xml_dtd" | "font" | "media" | "websocket" | "csp_report" | "imageset" | "web_manifest" | "speculative" | "json" | "other"; + /** + * Describes the reason why a given regular expression isn't supported. + */ + type UnsupportedRegexReason = "syntaxError" | "memoryLimitExceeded"; + interface MatchedRule { + /** + * A matching rule's ID. + */ + ruleId: number; + /** + * ID of the Ruleset this rule belongs to. + */ + rulesetId: string; + /** + * ID of the extension, if this rule belongs to a different extension. + * Optional. + */ + extensionId?: string; + } + /** + * Describes the type of the Rule.action.redirect.transform property. + */ + interface URLTransform { + /** + * The new scheme for the request. + * Optional. + */ + scheme?: URLTransformSchemeEnum; + /** + * The new username for the request. + * Optional. + */ + username?: string; + /** + * The new password for the request. + * Optional. + */ + password?: string; + /** + * The new host name for the request. + * Optional. + */ + host?: string; + /** + * The new port for the request. If empty, the existing port is cleared. + * Optional. + */ + port?: string; + /** + * The new path for the request. If empty, the existing path is cleared. + * Optional. + */ + path?: string; + /** + * The new query for the request. Should be either empty, in which case the existing query is cleared; or should begin with + * '?'. Cannot be specified if 'queryTransform' is specified. + * Optional. + */ + query?: string; + /** + * Add, remove or replace query key-value pairs. Cannot be specified if 'query' is specified. + * Optional. + */ + queryTransform?: URLTransformQueryTransformType; + /** + * The new fragment for the request. Should be either empty, in which case the existing fragment is cleared; or should + * begin with '#'. + * Optional. + */ + fragment?: string; + } + interface Rule { + /** + * An id which uniquely identifies a rule. Mandatory and should be >= 1. + */ + id: number; + /** + * Rule priority. Defaults to 1. When specified, should be >= 1 + * Optional. + */ + priority?: number; + /** + * The condition under which this rule is triggered. + */ + condition: RuleConditionType; + /** + * The action to take if this rule is matched. + */ + action: RuleActionType; + } + interface GetRulesFilter { + /** + * If specified, only rules with matching IDs are included. + * Optional. + */ + ruleIds?: number[]; + } + interface UpdateDynamicRulesOptionsType { + /** + * IDs of the rules to remove. Any invalid IDs will be ignored. + * Optional. + */ + removeRuleIds?: number[]; + /** + * Rules to add. + * Optional. + */ + addRules?: Rule[]; + } + interface UpdateSessionRulesOptionsType { + /** + * IDs of the rules to remove. Any invalid IDs will be ignored. + * Optional. + */ + removeRuleIds?: number[]; + /** + * Rules to add. + * Optional. + */ + addRules?: Rule[]; + } + interface UpdateEnabledRulesetsUpdateRulesetOptionsType { + /** + * Optional. + */ + disableRulesetIds?: string[]; + /** + * Optional. + */ + enableRulesetIds?: string[]; + } + interface UpdateStaticRulesOptionsType { + rulesetId: string; + /** + * Optional. + */ + disableRuleIds?: number[]; + /** + * Optional. + */ + enableRuleIds?: number[]; + } + interface GetDisabledRuleIdsOptionsType { + rulesetId: string; + } + interface IsRegexSupportedRegexOptionsType { + /** + * The regular expresson to check. + */ + regex: string; + /** + * Whether the 'regex' specified is case sensitive. + * Optional. + */ + isCaseSensitive?: boolean; + /** + * Whether the 'regex' specified requires capturing. Capturing is only required for redirect rules which specify a + * 'regexSubstition' action. + * Optional. + */ + requireCapturing?: boolean; + } + interface IsRegexSupportedCallbackResultType { + /** + * Whether the given regex is supported + */ + isSupported: boolean; + /** + * Specifies the reason why the regular expression is not supported. Only provided if 'isSupported' is false. + * Optional. + */ + reason?: UnsupportedRegexReason; + } + /** + * The details of the request to test. + */ + interface TestMatchOutcomeRequestType { + /** + * The URL of the hypothetical request. + */ + url: string; + /** + * The initiator URL (if any) for the hypothetical request. + * Optional. + */ + initiator?: string; + /** + * Standard HTTP method of the hypothetical request. + * Optional. + */ + method?: string; + /** + * The resource type of the hypothetical request. + */ + type: ResourceType; + /** + * The ID of the tab in which the hypothetical request takes place. Does not need to correspond to a real tab ID. + * Default is -1, meaning that the request isn't related to a tab. + * Optional. + */ + tabId?: number; + } + interface TestMatchOutcomeOptionsType { + /** + * Whether to account for rules from other installed extensions during rule evaluation. + * Optional. + */ + includeOtherExtensions?: boolean; + } + interface TestMatchOutcomeCallbackResultType { + /** + * The rules (if any) that match the hypothetical request. + */ + matchedRules: MatchedRule[]; + } + /** + * The new scheme for the request. + */ + type URLTransformSchemeEnum = "http" | "https" | "moz-extension"; + interface URLTransformQueryTransformAddOrReplaceParamsItemType { + key: string; + value: string; + /** + * If true, the query key is replaced only if it's already present. Otherwise, the key is also added if it's missing. + * Optional. + */ + replaceOnly?: boolean; + } + /** + * Add, remove or replace query key-value pairs. Cannot be specified if 'query' is specified. + */ + interface URLTransformQueryTransformType { + /** + * The list of query keys to be removed. + * Optional. + */ + removeParams?: string[]; + /** + * The list of query key-value pairs to be added or replaced. + * Optional. + */ + addOrReplaceParams?: URLTransformQueryTransformAddOrReplaceParamsItemType[]; + } + /** + * Specifies whether the network request is first-party or third-party to the domain from which it originated. If omitted, + * all requests are matched. + */ + type RuleConditionDomainTypeEnum = "firstParty" | "thirdParty"; + /** + * The condition under which this rule is triggered. + */ + interface RuleConditionType { + /** + * TODO: link to doc explaining supported pattern. The pattern which is matched against the network request url. + * Only one of 'urlFilter' or 'regexFilter' can be specified. + * Optional. + */ + urlFilter?: string; + /** + * Regular expression to match against the network request url. Only one of 'urlFilter' or 'regexFilter' can be specified. + * Optional. + */ + regexFilter?: string; + /** + * Whether 'urlFilter' or 'regexFilter' is case-sensitive. + * Optional. + */ + isUrlFilterCaseSensitive?: boolean; + /** + * The rule will only match network requests originating from the list of 'initiatorDomains'. If the list is omitted, + * the rule is applied to requests from all domains. + * Optional. + */ + initiatorDomains?: string[]; + /** + * The rule will not match network requests originating from the list of 'initiatorDomains'. + * If the list is empty or omitted, no domains are excluded. This takes precedence over 'initiatorDomains'. + * Optional. + */ + excludedInitiatorDomains?: string[]; + /** + * The rule will only match network requests when the domain matches one from the list of 'requestDomains'. + * If the list is omitted, the rule is applied to requests from all domains. + * Optional. + */ + requestDomains?: string[]; + /** + * The rule will not match network requests when the domains matches one from the list of 'excludedRequestDomains'. + * If the list is empty or omitted, no domains are excluded. This takes precedence over 'requestDomains'. + * Optional. + */ + excludedRequestDomains?: string[]; + /** + * List of resource types which the rule can match. When the rule action is 'allowAllRequests', + * this must be specified and may only contain 'main_frame' or 'sub_frame'. Cannot be specified if 'excludedResourceTypes' + * is specified. If neither of them is specified, all resource types except 'main_frame' are matched. + * Optional. + */ + resourceTypes?: ResourceType[]; + /** + * List of resource types which the rule won't match. Cannot be specified if 'resourceTypes' is specified. + * If neither of them is specified, all resource types except 'main_frame' are matched. + * Optional. + */ + excludedResourceTypes?: ResourceType[]; + /** + * List of HTTP request methods which the rule can match. Should be a lower-case method such as 'connect', 'delete', 'get', + * 'head', 'options', 'patch', 'post', 'put'.' + * Optional. + */ + requestMethods?: string[]; + /** + * List of request methods which the rule won't match. Cannot be specified if 'requestMethods' is specified. + * If neither of them is specified, all request methods are matched. + * Optional. + */ + excludedRequestMethods?: string[]; + /** + * Specifies whether the network request is first-party or third-party to the domain from which it originated. If omitted, + * all requests are matched. + * Optional. + */ + domainType?: RuleConditionDomainTypeEnum; + /** + * List of tabIds which the rule should match. An ID of -1 matches requests which don't originate from a tab. + * Only supported for session-scoped rules. + * Optional. + */ + tabIds?: number[]; + /** + * List of tabIds which the rule should not match. An ID of -1 excludes requests which don't originate from a tab. + * Only supported for session-scoped rules. + * Optional. + */ + excludedTabIds?: number[]; + } + type RuleActionTypeEnum = "block" | "redirect" | "allow" | "upgradeScheme" | "modifyHeaders" | "allowAllRequests"; + /** + * Describes how the redirect should be performed. Only valid when type is 'redirect'. + */ + interface RuleActionRedirectType { + /** + * Path relative to the extension directory. Should start with '/'. + * Optional. + */ + extensionPath?: string; + /** + * Url transformations to perform. + * Optional. + */ + transform?: URLTransform; + /** + * The redirect url. Redirects to JavaScript urls are not allowed. + * Optional. + */ + url?: string; + /** + * Substitution pattern for rules which specify a 'regexFilter'. The first match of regexFilter within the url will be + * replaced with this pattern. Within regexSubstitution, backslash-escaped digits (\1 to \9) + * can be used to insert the corresponding capture groups. \0 refers to the entire matching text. + * Optional. + */ + regexSubstitution?: string; + } + interface RuleActionRequestHeadersItemType { + /** + * The name of the request header to be modified. + */ + header: string; + /** + * The operation to be performed on a header. + */ + operation: "append" | "set" | "remove"; + /** + * The new value for the header. Must be specified for the 'append' and 'set' operations. + * Optional. + */ + value?: string; + } + interface RuleActionResponseHeadersItemType { + /** + * The name of the response header to be modified. + */ + header: string; + /** + * The operation to be performed on a header. + */ + operation: "append" | "set" | "remove"; + /** + * The new value for the header. Must be specified for the 'append' and 'set' operations. + * Optional. + */ + value?: string; + } + /** + * The action to take if this rule is matched. + */ + interface RuleActionType { + type: RuleActionTypeEnum; + /** + * Describes how the redirect should be performed. Only valid when type is 'redirect'. + * Optional. + */ + redirect?: RuleActionRedirectType; + /** + * The request headers to modify for the request. Only valid when type is 'modifyHeaders'. + * Optional. + */ + requestHeaders?: RuleActionRequestHeadersItemType[]; + /** + * The response headers to modify for the request. Only valid when type is 'modifyHeaders'. + * Optional. + */ + responseHeaders?: RuleActionResponseHeadersItemType[]; + } + interface Static { + /** + * Modifies the current set of dynamic rules for the extension. The rules with IDs listed in options. + * removeRuleIds are first removed, and then the rules given in options.addRules are added. + * These rules are persisted across browser sessions and extension updates. + * + * @returns Called when the dynamic rules have been updated + */ + updateDynamicRules(options: UpdateDynamicRulesOptionsType): Promise<void>; + /** + * Modifies the current set of session scoped rules for the extension. The rules with IDs listed in options. + * removeRuleIds are first removed, and then the rules given in options.addRules are added. + * These rules are not persisted across sessions and are backed in memory. + * + * @returns Called when the session rules have been updated + */ + updateSessionRules(options: UpdateSessionRulesOptionsType): Promise<void>; + /** + * Returns the ids for the current set of enabled static rulesets. + */ + getEnabledRulesets(): Promise<string[]>; + /** + * Modifies the static rulesets enabled/disabled state. + */ + updateEnabledRulesets(updateRulesetOptions: UpdateEnabledRulesetsUpdateRulesetOptionsType): Promise<void>; + /** + * Modified individual static rules enabled/disabled state. Changes to rules belonging to a disabled ruleset will take + * effect when the ruleset becomes enabled. + */ + updateStaticRules(options: UpdateStaticRulesOptionsType): Promise<void>; + /** + * Returns the remaining number of static rules an extension can enable + */ + getAvailableStaticRuleCount(): Promise<number>; + /** + * Returns the list of individual disabled static rules from a given static ruleset id. + */ + getDisabledRuleIds(options: GetDisabledRuleIdsOptionsType): Promise<number[]>; + /** + * Returns the current set of dynamic rules for the extension. + * + * @param filter Optional. An object to filter the set of dynamic rules for the extension. + */ + getDynamicRules(filter?: GetRulesFilter): Promise<Rule[]>; + /** + * Returns the current set of session scoped rules for the extension. + * + * @param filter Optional. An object to filter the set of session scoped rules for the extension. + */ + getSessionRules(filter?: GetRulesFilter): Promise<Rule[]>; + /** + * Checks if the given regular expression will be supported as a 'regexFilter' rule condition. + */ + isRegexSupported(regexOptions: IsRegexSupportedRegexOptionsType): Promise<IsRegexSupportedCallbackResultType>; + /** + * Checks if any of the extension's declarativeNetRequest rules would match a hypothetical request. + * + * @param request The details of the request to test. + * @param options Optional. + * @returns Called with the details of matched rules. + */ + testMatchOutcome(request: TestMatchOutcomeRequestType, options?: TestMatchOutcomeOptionsType): Promise<TestMatchOutcomeCallbackResultType>; + /** + * Ruleset ID for the dynamic rules added by the extension. + */ + DYNAMIC_RULESET_ID: "_dynamic"; + /** + * The minimum number of static rules guaranteed to an extension across its enabled static rulesets. + * Any rules above this limit will count towards the global static rule limit. + */ + GUARANTEED_MINIMUM_STATIC_RULES: number; + /** + * The maximum number of static Rulesets an extension can specify as part of the rule_resources manifest key. + */ + MAX_NUMBER_OF_STATIC_RULESETS: number; + /** + * The maximum number of static rules that can be disabled on each static ruleset. + */ + MAX_NUMBER_OF_DISABLED_STATIC_RULES: number; + /** + * The maximum number of static Rulesets an extension can enable at any one time. + */ + MAX_NUMBER_OF_ENABLED_STATIC_RULESETS: number; + /** + * Deprecated property returning the maximum number of dynamic and session rules an extension can add, + * replaced by MAX_NUMBER_OF_DYNAMIC_RULES/MAX_NUMBER_OF_SESSION_RULES. + */ + MAX_NUMBER_OF_DYNAMIC_AND_SESSION_RULES: number; + /** + * The maximum number of dynamic session rules an extension can add. + */ + MAX_NUMBER_OF_DYNAMIC_RULES: number; + /** + * The maximum number of dynamic session rules an extension can add. + */ + MAX_NUMBER_OF_SESSION_RULES: number; + /** + * The maximum number of regular expression rules that an extension can add. This limit is evaluated separately for the set + * of session rules, dynamic rules and those specified in the rule_resources file. + */ + MAX_NUMBER_OF_REGEX_RULES: number; + /** + * Ruleset ID for the session-scoped rules added by the extension. + */ + SESSION_RULESET_ID: "_session"; + } + } + /** + * Namespace: browser.devtools + */ + namespace Devtools { + interface Static { + inspectedWindow: InspectedWindow.Static; + network: Network.Static; + panels: Panels.Static; + } + } + /** + * Namespace: browser.dns + */ + namespace Dns { + /** + * An object encapsulating a DNS Record. + */ + interface DNSRecord { + /** + * The canonical hostname for this record. this value is empty if the record was not fetched with the 'canonical_name' + * flag. + * Optional. + */ + canonicalName?: string; + /** + * Record retreived with TRR. + */ + isTRR: string; + addresses: string[]; + } + type ResolveFlags = ResolveFlagsItemEnum[]; + type ResolveFlagsItemEnum = "allow_name_collisions" | "bypass_cache" | "canonical_name" | "disable_ipv4" | "disable_ipv6" | "disable_trr" | "offline" | "priority_low" | "priority_medium" | "speculate"; + interface Static { + /** + * Resolves a hostname to a DNS record. + * + * @param flags Optional. + */ + resolve(hostname: string, flags?: ResolveFlags): Promise<DNSRecord>; + } + } + /** + * Namespace: browser.downloads + */ + namespace Downloads { + type FilenameConflictAction = "uniquify" | "overwrite" | "prompt"; + type InterruptReason = "FILE_FAILED" | "FILE_ACCESS_DENIED" | "FILE_NO_SPACE" | "FILE_NAME_TOO_LONG" | "FILE_TOO_LARGE" | "FILE_VIRUS_INFECTED" | "FILE_TRANSIENT_ERROR" | "FILE_BLOCKED" | "FILE_SECURITY_CHECK_FAILED" | "FILE_TOO_SHORT" | "NETWORK_FAILED" | "NETWORK_TIMEOUT" | "NETWORK_DISCONNECTED" | "NETWORK_SERVER_DOWN" | "NETWORK_INVALID_REQUEST" | "SERVER_FAILED" | "SERVER_NO_RANGE" | "SERVER_BAD_CONTENT" | "SERVER_UNAUTHORIZED" | "SERVER_CERT_PROBLEM" | "SERVER_FORBIDDEN" | "USER_CANCELED" | "USER_SHUTDOWN" | "CRASH"; + /** + * <dl><dt>file</dt><dd>The download's filename is suspicious.</dd><dt>url</dt><dd>The download's URL is known to be + * malicious.</dd><dt>content</dt><dd>The downloaded file is known to be malicious.</dd><dt>uncommon</dt><dd> + * The download's URL is not commonly downloaded and could be dangerous.</dd><dt>safe</dt><dd> + * The download presents no known danger to the user's computer.</dd></dl>These string constants will never change, + * however the set of DangerTypes may change. + */ + type DangerType = "file" | "url" | "content" | "uncommon" | "host" | "unwanted" | "safe" | "accepted"; + /** + * <dl><dt>in_progress</dt><dd>The download is currently receiving data from the server.</dd><dt>interrupted</dt><dd> + * An error broke the connection with the file host.</dd><dt>complete</dt><dd>The download completed successfully.</dd></dl> + * These string constants will never change, however the set of States may change. + */ + type State = "in_progress" | "interrupted" | "complete"; + interface DownloadItem { + /** + * An identifier that is persistent across browser sessions. + */ + id: number; + /** + * Absolute URL. + */ + url: string; + /** + * Optional. + */ + referrer?: string; + /** + * Absolute local path. + */ + filename: string; + /** + * False if this download is recorded in the history, true if it is not recorded. + */ + incognito: boolean; + /** + * The cookie store ID of the contextual identity. + * Optional. + */ + cookieStoreId?: string; + /** + * Indication of whether this download is thought to be safe or known to be suspicious. + */ + danger: DangerType; + /** + * The file's MIME type. + * Optional. + */ + mime?: string; + /** + * Number of milliseconds between the unix epoch and when this download began. + */ + startTime: string; + /** + * Number of milliseconds between the unix epoch and when this download ended. + * Optional. + */ + endTime?: string; + /** + * Optional. + */ + estimatedEndTime?: string; + /** + * Indicates whether the download is progressing, interrupted, or complete. + */ + state: State; + /** + * True if the download has stopped reading data from the host, but kept the connection open. + */ + paused: boolean; + canResume: boolean; + /** + * Number indicating why a download was interrupted. + * Optional. + */ + error?: InterruptReason; + /** + * Number of bytes received so far from the host, without considering file compression. + */ + bytesReceived: number; + /** + * Number of bytes in the whole file, without considering file compression, or -1 if unknown. + */ + totalBytes: number; + /** + * Number of bytes in the whole file post-decompression, or -1 if unknown. + */ + fileSize: number; + exists: boolean; + /** + * Optional. + */ + byExtensionId?: string; + /** + * Optional. + */ + byExtensionName?: string; + } + interface StringDelta { + /** + * Optional. + */ + current?: string; + /** + * Optional. + */ + previous?: string; + } + interface DoubleDelta { + /** + * Optional. + */ + current?: number; + /** + * Optional. + */ + previous?: number; + } + interface BooleanDelta { + /** + * Optional. + */ + current?: boolean; + /** + * Optional. + */ + previous?: boolean; + } + /** + * A time specified as a Date object, a number or string representing milliseconds since the epoch, or an ISO 8601 string + */ + type DownloadTime = string | ExtensionTypes.DateType; + /** + * Parameters that combine to specify a predicate that can be used to select a set of downloads. + * Used for example in search() and erase() + */ + interface DownloadQuery { + /** + * This array of search terms limits results to <a href='#type-DownloadItem'>DownloadItems</a> whose <code>filename</code> + * or <code>url</code> contain all of the search terms that do not begin with a dash '-' and none of the search terms that + * do begin with a dash. + * Optional. + */ + query?: string[]; + /** + * Limits results to downloads that started before the given ms since the epoch. + * Optional. + */ + startedBefore?: DownloadTime; + /** + * Limits results to downloads that started after the given ms since the epoch. + * Optional. + */ + startedAfter?: DownloadTime; + /** + * Limits results to downloads that ended before the given ms since the epoch. + * Optional. + */ + endedBefore?: DownloadTime; + /** + * Limits results to downloads that ended after the given ms since the epoch. + * Optional. + */ + endedAfter?: DownloadTime; + /** + * Limits results to downloads whose totalBytes is greater than the given integer. + * Optional. + */ + totalBytesGreater?: number; + /** + * Limits results to downloads whose totalBytes is less than the given integer. + * Optional. + */ + totalBytesLess?: number; + /** + * Limits results to <a href='#type-DownloadItem'>DownloadItems</a> whose <code>filename</code> + * matches the given regular expression. + * Optional. + */ + filenameRegex?: string; + /** + * Limits results to <a href='#type-DownloadItem'>DownloadItems</a> whose <code>url</code> + * matches the given regular expression. + * Optional. + */ + urlRegex?: string; + /** + * Setting this integer limits the number of results. Otherwise, all matching <a href='#type-DownloadItem'>DownloadItems</a> + * will be returned. + * Optional. + */ + limit?: number; + /** + * Setting elements of this array to <a href='#type-DownloadItem'>DownloadItem</a> properties in order to sort the search + * results. For example, setting <code>orderBy='startTime'</code> sorts the <a href='#type-DownloadItem'>DownloadItems</a> + * by their start time in ascending order. To specify descending order, prefix <code>orderBy</code> + * with a hyphen: '-startTime'. + * Optional. + */ + orderBy?: string[]; + /** + * Optional. + */ + id?: number; + /** + * Absolute URL. + * Optional. + */ + url?: string; + /** + * Absolute local path. + * Optional. + */ + filename?: string; + /** + * The cookie store ID of the contextual identity. + * Optional. + */ + cookieStoreId?: string; + /** + * Indication of whether this download is thought to be safe or known to be suspicious. + * Optional. + */ + danger?: DangerType; + /** + * The file's MIME type. + * Optional. + */ + mime?: string; + /** + * Optional. + */ + startTime?: string; + /** + * Optional. + */ + endTime?: string; + /** + * Indicates whether the download is progressing, interrupted, or complete. + * Optional. + */ + state?: State; + /** + * True if the download has stopped reading data from the host, but kept the connection open. + * Optional. + */ + paused?: boolean; + /** + * Why a download was interrupted. + * Optional. + */ + error?: InterruptReason; + /** + * Number of bytes received so far from the host, without considering file compression. + * Optional. + */ + bytesReceived?: number; + /** + * Number of bytes in the whole file, without considering file compression, or -1 if unknown. + * Optional. + */ + totalBytes?: number; + /** + * Number of bytes in the whole file post-decompression, or -1 if unknown. + * Optional. + */ + fileSize?: number; + /** + * Optional. + */ + exists?: boolean; + } + /** + * What to download and how. + */ + interface DownloadOptionsType { + /** + * The URL to download. + */ + url: string; + /** + * A file path relative to the Downloads directory to contain the downloaded file. + * Optional. + */ + filename?: string; + /** + * Whether to associate the download with a private browsing session. + * Optional. + */ + incognito?: boolean; + /** + * The cookie store ID of the contextual identity; requires "cookies" permission. + * Optional. + */ + cookieStoreId?: string; + /** + * Optional. + */ + conflictAction?: FilenameConflictAction; + /** + * Use a file-chooser to allow the user to select a filename. If the option is not specified, + * the file chooser will be shown only if the Firefox "Always ask you where to save files" option is enabled (i.e. + * the pref <code>browser.download.useDownloadDir</code> is set to <code>false</code>). + * Optional. + */ + saveAs?: boolean; + /** + * The HTTP method to use if the URL uses the HTTP[S] protocol. + * Optional. + */ + method?: DownloadOptionsTypeMethodEnum; + /** + * Extra HTTP headers to send with the request if the URL uses the HTTP[s] protocol. Each header is represented as a + * dictionary containing the keys <code>name</code> and either <code>value</code> or <code>binaryValue</code>, + * restricted to those allowed by XMLHttpRequest. + * Optional. + */ + headers?: DownloadOptionsTypeHeadersItemType[]; + /** + * Post body. + * Optional. + */ + body?: string; + /** + * When this flag is set to <code>true</code>, then the browser will allow downloads to proceed after encountering HTTP + * errors such as <code>404 Not Found</code>. + * Optional. + */ + allowHttpErrors?: boolean; + } + interface GetFileIconOptionsType { + /** + * The size of the icon. The returned icon will be square with dimensions size * size pixels. + * The default size for the icon is 32x32 pixels. + * Optional. + */ + size?: number; + } + interface OnChangedDownloadDeltaType { + /** + * The <code>id</code> of the <a href='#type-DownloadItem'>DownloadItem</a> that changed. + */ + id: number; + /** + * Describes a change in a <a href='#type-DownloadItem'>DownloadItem</a>'s <code>url</code>. + * Optional. + */ + url?: StringDelta; + /** + * Describes a change in a <a href='#type-DownloadItem'>DownloadItem</a>'s <code>filename</code>. + * Optional. + */ + filename?: StringDelta; + /** + * Describes a change in a <a href='#type-DownloadItem'>DownloadItem</a>'s <code>danger</code>. + * Optional. + */ + danger?: StringDelta; + /** + * Describes a change in a <a href='#type-DownloadItem'>DownloadItem</a>'s <code>mime</code>. + * Optional. + */ + mime?: StringDelta; + /** + * Describes a change in a <a href='#type-DownloadItem'>DownloadItem</a>'s <code>startTime</code>. + * Optional. + */ + startTime?: StringDelta; + /** + * Describes a change in a <a href='#type-DownloadItem'>DownloadItem</a>'s <code>endTime</code>. + * Optional. + */ + endTime?: StringDelta; + /** + * Describes a change in a <a href='#type-DownloadItem'>DownloadItem</a>'s <code>state</code>. + * Optional. + */ + state?: StringDelta; + /** + * Optional. + */ + canResume?: BooleanDelta; + /** + * Describes a change in a <a href='#type-DownloadItem'>DownloadItem</a>'s <code>paused</code>. + * Optional. + */ + paused?: BooleanDelta; + /** + * Describes a change in a <a href='#type-DownloadItem'>DownloadItem</a>'s <code>error</code>. + * Optional. + */ + error?: StringDelta; + /** + * Describes a change in a <a href='#type-DownloadItem'>DownloadItem</a>'s <code>totalBytes</code>. + * Optional. + */ + totalBytes?: DoubleDelta; + /** + * Describes a change in a <a href='#type-DownloadItem'>DownloadItem</a>'s <code>fileSize</code>. + * Optional. + */ + fileSize?: DoubleDelta; + /** + * Optional. + */ + exists?: BooleanDelta; + } + /** + * The HTTP method to use if the URL uses the HTTP[S] protocol. + */ + type DownloadOptionsTypeMethodEnum = "GET" | "POST"; + interface DownloadOptionsTypeHeadersItemType { + /** + * Name of the HTTP header. + */ + name: string; + /** + * Value of the HTTP header. + */ + value: string; + } + interface Static { + /** + * Download a URL. If the URL uses the HTTP[S] protocol, then the request will include all cookies currently set for its + * hostname. If both <code>filename</code> and <code>saveAs</code> are specified, then the Save As dialog will be displayed, + * pre-populated with the specified <code>filename</code>. If the download started successfully, <code>callback</code> + * will be called with the new <a href='#type-DownloadItem'>DownloadItem</a>'s <code>downloadId</code>. + * If there was an error starting the download, then <code>callback</code> will be called with <code> + * downloadId=undefined</code> and <a href='extension.html#property-lastError'>chrome.extension.lastError</a> + * will contain a descriptive string. The error strings are not guaranteed to remain backwards compatible between releases. + * You must not parse it. + * + * @param options What to download and how. + */ + download(options: DownloadOptionsType): Promise<number>; + /** + * Find <a href='#type-DownloadItem'>DownloadItems</a>. Set <code>query</code> to the empty object to get all <a + * href='#type-DownloadItem'>DownloadItems</a>. To get a specific <a href='#type-DownloadItem'>DownloadItem</a>, + * set only the <code>id</code> field. + */ + search(query: DownloadQuery): Promise<DownloadItem[]>; + /** + * Pause the download. If the request was successful the download is in a paused state. Otherwise <a href='extension. + * html#property-lastError'>chrome.extension.lastError</a> contains an error message. + * The request will fail if the download is not active. + * + * @param downloadId The id of the download to pause. + */ + pause(downloadId: number): Promise<void>; + /** + * Resume a paused download. If the request was successful the download is in progress and unpaused. + * Otherwise <a href='extension.html#property-lastError'>chrome.extension.lastError</a> contains an error message. + * The request will fail if the download is not active. + * + * @param downloadId The id of the download to resume. + */ + resume(downloadId: number): Promise<void>; + /** + * Cancel a download. When <code>callback</code> is run, the download is cancelled, completed, + * interrupted or doesn't exist anymore. + * + * @param downloadId The id of the download to cancel. + */ + cancel(downloadId: number): Promise<void>; + /** + * Retrieve an icon for the specified download. For new downloads, file icons are available after the <a + * href='#event-onCreated'>onCreated</a> event has been received. The image returned by this function while a download is + * in progress may be different from the image returned after the download is complete. + * Icon retrieval is done by querying the underlying operating system or toolkit depending on the platform. + * The icon that is returned will therefore depend on a number of factors including state of the download, platform, + * registered file types and visual theme. If a file icon cannot be determined, <a href='extension. + * html#property-lastError'>chrome.extension.lastError</a> will contain an error message. + * + * @param downloadId The identifier for the download. + * @param options Optional. + */ + getFileIcon(downloadId: number, options?: GetFileIconOptionsType): Promise<string>; + /** + * Open the downloaded file. + */ + open(downloadId: number): Promise<void>; + /** + * Show the downloaded file in its folder in a file manager. + */ + show(downloadId: number): Promise<boolean>; + showDefaultFolder(): void; + /** + * Erase matching <a href='#type-DownloadItem'>DownloadItems</a> from history + */ + erase(query: DownloadQuery): Promise<number[]>; + removeFile(downloadId: number): Promise<void>; + /** + * This event fires with the <a href='#type-DownloadItem'>DownloadItem</a> object when a download begins. + */ + onCreated: Events.Event<(downloadItem: DownloadItem) => void>; + /** + * Fires with the <code>downloadId</code> when a download is erased from history. + * + * @param downloadId The <code>id</code> of the <a href='#type-DownloadItem'>DownloadItem</a> that was erased. + */ + onErased: Events.Event<(downloadId: number) => void>; + /** + * When any of a <a href='#type-DownloadItem'>DownloadItem</a>'s properties except <code>bytesReceived</code> changes, + * this event fires with the <code>downloadId</code> and an object containing the properties that changed. + */ + onChanged: Events.Event<(downloadDelta: OnChangedDownloadDeltaType) => void>; + } + } + /** + * Namespace: browser.events + */ + namespace Events { + /** + * Description of a declarative rule for handling events. + */ + interface Rule { + /** + * Optional identifier that allows referencing this rule. + * Optional. + */ + id?: string; + /** + * Tags can be used to annotate rules and perform operations on sets of rules. + * Optional. + */ + tags?: string[]; + /** + * List of conditions that can trigger the actions. + */ + conditions: unknown[]; + /** + * List of actions that are triggered if one of the condtions is fulfilled. + */ + actions: unknown[]; + /** + * Optional priority of this rule. Defaults to 100. + * Optional. + */ + priority?: number; + } + /** + * An object which allows the addition and removal of listeners for a Chrome event. + */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + interface Event<T extends (...args: any[]) => any> { + /** + * Registers an event listener <em>callback</em> to an event. + * + * @param callback Called when an event occurs. The parameters of this function depend on the type of event. + * @param ...params Further parameters, depending on the event. + */ + addListener(callback: T, ...params: unknown[]): void; + /** + * Deregisters an event listener <em>callback</em> from an event. + * + * @param callback Listener that shall be unregistered. + */ + removeListener(callback: T): void; + /** + * @param callback Listener whose registration status shall be tested. + * @returns True if <em>callback</em> is registered to the event. + */ + hasListener(callback: T): boolean; + } + /** + * Filters URLs for various criteria. See <a href='events#filtered'>event filtering</a>. All criteria are case sensitive. + */ + interface UrlFilter { + /** + * Matches if the host name of the URL contains a specified string. To test whether a host name component has a prefix + * 'foo', use hostContains: '.foo'. This matches 'www.foobar.com' and 'foo.com', because an implicit dot is added at the + * beginning of the host name. Similarly, hostContains can be used to match against component suffix ('foo.') + * and to exactly match against components ('.foo.'). Suffix- and exact-matching for the last components need to be done + * separately using hostSuffix, because no implicit dot is added at the end of the host name. + * Optional. + */ + hostContains?: string; + /** + * Matches if the host name of the URL is equal to a specified string. + * Optional. + */ + hostEquals?: string; + /** + * Matches if the host name of the URL starts with a specified string. + * Optional. + */ + hostPrefix?: string; + /** + * Matches if the host name of the URL ends with a specified string. + * Optional. + */ + hostSuffix?: string; + /** + * Matches if the path segment of the URL contains a specified string. + * Optional. + */ + pathContains?: string; + /** + * Matches if the path segment of the URL is equal to a specified string. + * Optional. + */ + pathEquals?: string; + /** + * Matches if the path segment of the URL starts with a specified string. + * Optional. + */ + pathPrefix?: string; + /** + * Matches if the path segment of the URL ends with a specified string. + * Optional. + */ + pathSuffix?: string; + /** + * Matches if the query segment of the URL contains a specified string. + * Optional. + */ + queryContains?: string; + /** + * Matches if the query segment of the URL is equal to a specified string. + * Optional. + */ + queryEquals?: string; + /** + * Matches if the query segment of the URL starts with a specified string. + * Optional. + */ + queryPrefix?: string; + /** + * Matches if the query segment of the URL ends with a specified string. + * Optional. + */ + querySuffix?: string; + /** + * Matches if the URL (without fragment identifier) contains a specified string. Port numbers are stripped from the URL if + * they match the default port number. + * Optional. + */ + urlContains?: string; + /** + * Matches if the URL (without fragment identifier) is equal to a specified string. Port numbers are stripped from the URL + * if they match the default port number. + * Optional. + */ + urlEquals?: string; + /** + * Matches if the URL (without fragment identifier) matches a specified regular expression. + * Port numbers are stripped from the URL if they match the default port number. The regular expressions use the <a + * href="https://github.com/google/re2/blob/master/doc/syntax.txt">RE2 syntax</a>. + * Optional. + */ + urlMatches?: string; + /** + * Matches if the URL without query segment and fragment identifier matches a specified regular expression. + * Port numbers are stripped from the URL if they match the default port number. The regular expressions use the <a + * href="https://github.com/google/re2/blob/master/doc/syntax.txt">RE2 syntax</a>. + * Optional. + */ + originAndPathMatches?: string; + /** + * Matches if the URL (without fragment identifier) starts with a specified string. Port numbers are stripped from the URL + * if they match the default port number. + * Optional. + */ + urlPrefix?: string; + /** + * Matches if the URL (without fragment identifier) ends with a specified string. Port numbers are stripped from the URL if + * they match the default port number. + * Optional. + */ + urlSuffix?: string; + /** + * Matches if the scheme of the URL is equal to any of the schemes specified in the array. + * Optional. + */ + schemes?: string[]; + /** + * Matches if the port of the URL is contained in any of the specified port lists. For example <code>[80, 443, [1000, 1200]] + * </code> matches all requests on port 80, 443 and in the range 1000-1200. + * Optional. + */ + ports?: Array<number | [ + number, + number + ]>; + } + interface Static { + [s: string]: unknown; + } + } + /** + * Namespace: browser.experiments + */ + namespace Experiments { + interface ExperimentAPI { + schema: ExperimentURL; + /** + * Optional. + */ + parent?: ExperimentAPIParentType; + /** + * Optional. + */ + child?: ExperimentAPIChildType; + } + type ExperimentURL = string; + type APIPaths = APIPath[]; + type APIPath = string[]; + type APIEvents = APIEvent[]; + type APIEvent = "startup"; + type APIParentScope = "addon_parent" | "content_parent" | "devtools_parent"; + type APIChildScope = "addon_child" | "content_child" | "devtools_child"; + interface ExperimentAPIParentType { + /** + * Optional. + */ + events?: APIEvents; + /** + * Optional. + */ + paths?: APIPaths; + script: ExperimentURL; + /** + * Optional. + */ + scopes?: APIParentScope[]; + } + interface ExperimentAPIChildType { + paths: APIPaths; + script: ExperimentURL; + scopes: APIChildScope[]; + } + interface Static { + [s: string]: unknown; + } + } + /** + * Namespace: browser.extensionTypes + */ + namespace ExtensionTypes { + /** + * The format of an image. + */ + type ImageFormat = "jpeg" | "png"; + /** + * Details about the format, quality, area and scale of the capture. + */ + interface ImageDetails { + /** + * The format of the resulting image. Default is <code>"jpeg"</code>. + * Optional. + */ + format?: ImageFormat; + /** + * When format is <code>"jpeg"</code>, controls the quality of the resulting image. This value is ignored for PNG images. + * As quality is decreased, the resulting image will have more visual artifacts, and the number of bytes needed to store + * it will decrease. + * Optional. + */ + quality?: number; + /** + * The area of the document to capture, in CSS pixels, relative to the page. If omitted, capture the visible viewport. + * Optional. + */ + rect?: ImageDetailsRectType; + /** + * The scale of the resulting image. Defaults to <code>devicePixelRatio</code>. + * Optional. + */ + scale?: number; + /** + * If true, temporarily resets the scroll position of the document to 0. Only takes effect if rect is also specified. + * Optional. + */ + resetScrollPosition?: boolean; + } + /** + * The soonest that the JavaScript or CSS will be injected into the tab. + */ + type RunAt = "document_start" | "document_end" | "document_idle"; + /** + * The JavaScript world for a script to execute within. <code>ISOLATED</code> is the default execution environment of + * content scripts, <code>MAIN</code> is the web page's execution environment. + */ + type ExecutionWorld = "ISOLATED" | "MAIN"; + /** + * The origin of the CSS to inject, this affects the cascading order (priority) of the stylesheet. + */ + type CSSOrigin = "user" | "author"; + /** + * Details of the script or CSS to inject. Either the code or the file property must be set, + * but both may not be set at the same time. + */ + interface InjectDetails { + /** + * JavaScript or CSS code to inject.<br><br><b>Warning:</b><br>Be careful using the <code>code</code> parameter. + * Incorrect use of it may open your extension to <a href="https://en.wikipedia.org/wiki/Cross-site_scripting"> + * cross site scripting</a> attacks. + * Optional. + */ + code?: string; + /** + * JavaScript or CSS file to inject. + * Optional. + */ + file?: string; + /** + * If allFrames is <code>true</code>, implies that the JavaScript or CSS should be injected into all frames of current page. + * By default, it's <code>false</code> and is only injected into the top frame. + * Optional. + */ + allFrames?: boolean; + /** + * If matchAboutBlank is true, then the code is also injected in about:blank and about:srcdoc frames if your extension has + * access to its parent document. Code cannot be inserted in top-level about:-frames. By default it is <code>false</code>. + * Optional. + */ + matchAboutBlank?: boolean; + /** + * The ID of the frame to inject the script into. This may not be used in combination with <code>allFrames</code>. + * Optional. + */ + frameId?: number; + /** + * The soonest that the JavaScript or CSS will be injected into the tab. Defaults to "document_idle". + * Optional. + */ + runAt?: RunAt; + /** + * The css origin of the stylesheet to inject. Defaults to "author". + * Optional. + */ + cssOrigin?: CSSOrigin; + } + type DateType = string | number | Date; + type ExtensionFileOrCode = ExtensionFileOrCodeC1Type | ExtensionFileOrCodeC2Type; + /** + * A plain JSON value + */ + interface PlainJSONValue { + [s: string]: unknown; + } + /** + * The area of the document to capture, in CSS pixels, relative to the page. If omitted, capture the visible viewport. + */ + interface ImageDetailsRectType { + x: number; + y: number; + width: number; + height: number; + } + interface ExtensionFileOrCodeC1Type { + file: Browser.Manifest.ExtensionURL; + } + interface ExtensionFileOrCodeC2Type { + code: string; + } + interface Static { + [s: string]: unknown; + } + } + /** + * Namespace: browser.extension + */ + namespace Extension { + /** + * The type of extension view. + */ + type ViewType = "tab" | "popup" | "sidebar"; + interface GetViewsFetchPropertiesType { + /** + * The type of view to get. If omitted, returns all views (including background pages and tabs). Valid values: 'tab', + * 'popup', 'sidebar'. + * Optional. + */ + type?: ViewType; + /** + * The window to restrict the search to. If omitted, returns all views. + * Optional. + */ + windowId?: number; + /** + * Find a view according to a tab id. If this field is omitted, returns all views. + * Optional. + */ + tabId?: number; + } + interface Static { + /** + * Returns an array of the JavaScript 'window' objects for each of the pages running inside the current extension. + * + * @param fetchProperties Optional. + * @returns Array of global objects + */ + getViews(fetchProperties?: GetViewsFetchPropertiesType): Window[]; + /** + * Returns the JavaScript 'window' object for the background page running inside the current extension. + * Returns null if the extension has no background page. + */ + getBackgroundPage(): Window; + /** + * Retrieves the state of the extension's access to Incognito-mode (as determined by the user-controlled 'Allowed in + * Incognito' checkbox. + */ + isAllowedIncognitoAccess(): Promise<boolean>; + /** + * Retrieves the state of the extension's access to the 'file://' scheme (as determined by the user-controlled 'Allow + * access to File URLs' checkbox. + */ + isAllowedFileSchemeAccess(): Promise<boolean>; + /** + * True for content scripts running inside incognito tabs, and for extension pages running inside an incognito process. + * The latter only applies to extensions with 'split' incognito_behavior. + * Optional. + */ + inIncognitoContext?: boolean; + } + } + /** + * Namespace: browser.find + */ + namespace Find { + interface RangeData { + /** + * The index of the frame containing the match. 0 corresponds to the parent window. Note that the order of objects in the + * rangeData array will sequentially line up with the order of frame indexes: for example, + * framePos for the first sequence of rangeData objects will be 0, framePos for the next sequence will be 1, and so on. + */ + framePos: number; + /** + * The ordinal position of the text node in which the match started. + */ + startTextNodePos: number; + /** + * The ordinal position of the text node in which the match ended. + */ + endTextNodePos: number; + /** + * The ordinal string position of the start of the matched word within start text node. + * If match word include in single text node, Extension can get match word between startOffset and endOffset string index + * in the single text node. + */ + startOffset: number; + /** + * The ordinal string position of the end of the matched word within end text node. + */ + endOffset: number; + } + interface Rectangle { + /** + * Pixels from the top. + */ + top: number; + /** + * Pixels from the left. + */ + left: number; + /** + * Pixels from the bottom. + */ + bottom: number; + /** + * Pixels from the right. + */ + right: number; + } + interface RectsAndTexts { + /** + * Rectangles relative to the top-left of the viewport. + */ + rectList: Rectangle[]; + /** + * an array of strings, corresponding to the rectList array. The entry at textList[i] + * contains the part of the match bounded by the rectangle at rectList[i]. + */ + textList: string[]; + } + interface RectData { + /** + * The index of the frame containing the match. 0 corresponds to the parent window. Note that the order of objects in the + * rangeData array will sequentially line up with the order of frame indexes: for example, + * framePos for the first sequence of rangeData objects will be 0, framePos for the next sequence will be 1, and so on. + */ + rectsAndTexts: RectsAndTexts; + /** + * The complete text of the match. + */ + text: string; + } + interface FindResult { + /** + * The number of results found. + */ + count: number; + /** + * If includeRangeData was given in the options parameter, then this property will be included. + * It is provided as an array of RangeData objects, one for each match. Each RangeData object describes where in the DOM + * tree the match was found. This would enable, for example, an extension to get the text surrounding each match, + * so as to display context for the matches. The items correspond to the items given in rectData, so rangeData[i] + * describes the same match as rectData[i]. + * Optional. + */ + rangeData?: RangeData[]; + /** + * If includeRectData was given in the options parameter, then this property will be included. + * It is an array of RectData objects. It contains client rectangles for all the text matched in the search, + * relative to the top-left of the viewport. Extensions can use this to provide custom highlighting of the results. + * Optional. + */ + rectData?: RectData[]; + } + /** + * Search parameters. + */ + interface FindParamsType { + /** + * Tab to query. Defaults to the active tab. + * Optional. + */ + tabId?: number; + /** + * Find only ranges with case sensitive match. + * Optional. + */ + caseSensitive?: boolean; + /** + * Find only ranges with diacritic sensitive match. + * Optional. + */ + matchDiacritics?: boolean; + /** + * Find only ranges that match entire word. + * Optional. + */ + entireWord?: boolean; + /** + * Return rectangle data which describes visual position of search results. + * Optional. + */ + includeRectData?: boolean; + /** + * Return range data which provides range data in a serializable form. + * Optional. + */ + includeRangeData?: boolean; + } + /** + * highlightResults parameters + */ + interface HighlightResultsParamsType { + /** + * Found range to be highlighted. Default highlights all ranges. + * Optional. + */ + rangeIndex?: number; + /** + * Tab to highlight. Defaults to the active tab. + * Optional. + */ + tabId?: number; + /** + * Don't scroll to highlighted item. + * Optional. + */ + noScroll?: boolean; + } + interface Static { + /** + * Search for text in document and store found ranges in array, in document order. + * + * @param queryphrase The string to search for. + * @param params Optional. Search parameters. + */ + find(queryphrase: string, params?: FindParamsType): Promise<FindResult>; + /** + * Highlight a range + * + * @param params Optional. highlightResults parameters + */ + highlightResults(params?: HighlightResultsParamsType): Promise<void>; + /** + * Remove all highlighting from previous searches. + * + * @param tabId Optional. Tab to highlight. Defaults to the active tab. + */ + removeHighlighting(tabId?: number): Promise<void>; + } + } + /** + * Namespace: browser.geckoProfiler + */ + namespace GeckoProfiler { + type ProfilerFeature = "java" | "js" | "mainthreadio" | "fileio" | "fileioall" | "nomarkerstacks" | "screenshots" | "seqstyle" | "stackwalk" | "jsallocations" | "nostacksampling" | "nativeallocations" | "ipcmessages" | "audiocallbacktracing" | "cpu" | "notimerresolutionchange" | "cpuallthreads" | "samplingallthreads" | "markersallthreads" | "unregisteredthreads" | "processcpu" | "power" | "responsiveness" | "cpufreq" | "bandwidth" | "memory" | "tracing" | "sandbox" | "flows"; + type supports = "windowLength"; + interface StartSettingsType { + /** + * The maximum size in bytes of the buffer used to store profiling data. A larger value allows capturing a profile that + * covers a greater amount of time. + */ + bufferSize: number; + /** + * The length of the window of time that's kept in the buffer. Any collected samples are discarded as soon as they are + * older than the number of seconds specified in this setting. Zero means no duration restriction. + * Optional. + */ + windowLength?: number; + /** + * Interval in milliseconds between samples of profiling data. A smaller value will increase the detail of the profiles + * captured. + */ + interval: number; + /** + * A list of active features for the profiler. + */ + features: ProfilerFeature[]; + /** + * A list of thread names for which to capture profiles. + * Optional. + */ + threads?: string[]; + } + interface Static { + /** + * Starts the profiler with the specified settings. + */ + start(settings: StartSettingsType): void; + /** + * Stops the profiler and discards any captured profile data. + */ + stop(): void; + /** + * Pauses the profiler, keeping any profile data that is already written. + */ + pause(): void; + /** + * Resumes the profiler with the settings that were initially used to start it. + */ + resume(): void; + /** + * Gathers the profile data from the current profiling session, and writes it to disk. + * The returned promise resolves to a path that locates the created file. + * + * @param fileName The name of the file inside the profile/profiler directory + */ + dumpProfileToFile(fileName: string): void; + /** + * Gathers the profile data from the current profiling session. + */ + getProfile(): void; + /** + * Gathers the profile data from the current profiling session. The returned promise resolves to an array buffer that + * contains a JSON string. + */ + getProfileAsArrayBuffer(): void; + /** + * Gathers the profile data from the current profiling session. The returned promise resolves to an array buffer that + * contains a gzipped JSON string. + */ + getProfileAsGzippedArrayBuffer(): void; + /** + * Gets the debug symbols for a particular library. + * + * @param debugName The name of the library's debug file. For example, 'xul.pdb + * @param breakpadId The Breakpad ID of the library + */ + getSymbols(debugName: string, breakpadId: string): void; + /** + * Fires when the profiler starts/stops running. + * + * @param isRunning Whether the profiler is running or not. Pausing the profiler will not affect this value. + */ + onRunning: Events.Event<(isRunning: boolean) => void>; + } + } + /** + * Namespace: browser.history + */ + namespace History { + /** + * The $(topic:transition-types)[transition type] for this visit from its referrer. + */ + type TransitionType = "link" | "typed" | "auto_bookmark" | "auto_subframe" | "manual_subframe" | "generated" | "auto_toplevel" | "form_submit" | "reload" | "keyword" | "keyword_generated"; + /** + * An object encapsulating one result of a history query. + */ + interface HistoryItem { + /** + * The unique identifier for the item. + */ + id: string; + /** + * The URL navigated to by a user. + * Optional. + */ + url?: string; + /** + * The title of the page when it was last loaded. + * Optional. + */ + title?: string; + /** + * When this page was last loaded, represented in milliseconds since the epoch. + * Optional. + */ + lastVisitTime?: number; + /** + * The number of times the user has navigated to this page. + * Optional. + */ + visitCount?: number; + /** + * The number of times the user has navigated to this page by typing in the address. + * Optional. + */ + typedCount?: number; + } + /** + * An object encapsulating one visit to a URL. + */ + interface VisitItem { + /** + * The unique identifier for the item. + */ + id: string; + /** + * The unique identifier for this visit. + */ + visitId: string; + /** + * When this visit occurred, represented in milliseconds since the epoch. + * Optional. + */ + visitTime?: number; + /** + * The visit ID of the referrer. + */ + referringVisitId: string; + /** + * The $(topic:transition-types)[transition type] for this visit from its referrer. + */ + transition: TransitionType; + } + interface SearchQueryType { + /** + * A free-text query to the history service. Leave empty to retrieve all pages. + */ + text: string; + /** + * Limit results to those visited after this date. If not specified, this defaults to 24 hours in the past. + * Optional. + */ + startTime?: ExtensionTypes.DateType; + /** + * Limit results to those visited before this date. + * Optional. + */ + endTime?: ExtensionTypes.DateType; + /** + * The maximum number of results to retrieve. Defaults to 100. + * Optional. + */ + maxResults?: number; + } + interface GetVisitsDetailsType { + /** + * The URL for which to retrieve visit information. It must be in the format as returned from a call to history.search. + */ + url: string; + } + interface AddUrlDetailsType { + /** + * The URL to add. Must be a valid URL that can be added to history. + */ + url: string; + /** + * The title of the page. + * Optional. + */ + title?: string; + /** + * The $(topic:transition-types)[transition type] for this visit from its referrer. + * Optional. + */ + transition?: TransitionType; + /** + * The date when this visit occurred. + * Optional. + */ + visitTime?: ExtensionTypes.DateType; + } + interface DeleteUrlDetailsType { + /** + * The URL to remove. + */ + url: string; + } + interface DeleteRangeRangeType { + /** + * Items added to history after this date. + */ + startTime: ExtensionTypes.DateType; + /** + * Items added to history before this date. + */ + endTime: ExtensionTypes.DateType; + } + interface OnVisitRemovedRemovedType { + /** + * True if all history was removed. If true, then urls will be empty. + */ + allHistory: boolean; + urls: string[]; + } + interface OnTitleChangedChangedType { + /** + * The URL for which the title has changed + */ + url: string; + /** + * The new title for the URL. + */ + title: string; + } + interface Static { + /** + * Searches the history for the last visit time of each page matching the query. + */ + search(query: SearchQueryType): Promise<HistoryItem[]>; + /** + * Retrieves information about visits to a URL. + */ + getVisits(details: GetVisitsDetailsType): Promise<VisitItem[]>; + /** + * Adds a URL to the history with a default visitTime of the current time and a default $(topic:transition-types) + * [transition type] of "link". + */ + addUrl(details: AddUrlDetailsType): Promise<void>; + /** + * Removes all occurrences of the given URL from the history. + */ + deleteUrl(details: DeleteUrlDetailsType): Promise<void>; + /** + * Removes all items within the specified date range from the history. Pages will not be removed from the history unless + * all visits fall within the range. + */ + deleteRange(range: DeleteRangeRangeType): Promise<void>; + /** + * Deletes all items from the history. + */ + deleteAll(): Promise<void>; + /** + * Fired when a URL is visited, providing the HistoryItem data for that URL. This event fires before the page has loaded. + */ + onVisited: Events.Event<(result: HistoryItem) => void>; + /** + * Fired when one or more URLs are removed from the history service. When all visits have been removed the URL is purged + * from history. + */ + onVisitRemoved: Events.Event<(removed: OnVisitRemovedRemovedType) => void>; + /** + * Fired when the title of a URL is changed in the browser history. + */ + onTitleChanged: Events.Event<(changed: OnTitleChangedChangedType) => void>; + } + } + /** + * Namespace: browser.i18n + */ + namespace I18n { + /** + * An ISO language code such as <code>en</code> or <code>fr</code>. For a complete list of languages supported by this + * method, see <a href='http://src.chromium.org/viewvc/chrome/trunk/src/third_party/cld/languages/internal/languages.cc'> + * kLanguageInfoTable</a>. For an unknown language, <code>und</code> will be returned, which means that [percentage] + * of the text is unknown to CLD + */ + type LanguageCode = string; + /** + * LanguageDetectionResult object that holds detected langugae reliability and array of DetectedLanguage + */ + interface DetectLanguageCallbackResultType { + /** + * CLD detected language reliability + */ + isReliable: boolean; + /** + * array of detectedLanguage + */ + languages: DetectLanguageCallbackResultTypeLanguagesItemType[]; + } + /** + * DetectedLanguage object that holds detected ISO language code and its percentage in the input string + */ + interface DetectLanguageCallbackResultTypeLanguagesItemType { + language: LanguageCode; + /** + * The percentage of the detected language + */ + percentage: number; + } + interface Static { + /** + * Gets the accept-languages of the browser. This is different from the locale used by the browser; to get the locale, + * use $(ref:i18n.getUILanguage). + */ + getAcceptLanguages(): Promise<LanguageCode[]>; + /** + * Gets the localized string for the specified message. If the message is missing, this method returns an empty string (''). + * If the format of the <code>getMessage()</code> call is wrong — for example, <em>messageName</em> + * is not a string or the <em>substitutions</em> array has more than 9 elements — this method returns <code> + * undefined</code>. + * + * @param messageName The name of the message, as specified in the <code>$(topic:i18n-messages)[messages.json]</code> file. + * @param substitutions Optional. Substitution strings, if the message requires any. + * @returns Message localized for current locale. + */ + getMessage(messageName: string, substitutions?: string[] | string): Promise<string>; + /** + * Gets the browser UI language of the browser. This is different from $(ref:i18n.getAcceptLanguages) + * which returns the preferred user languages. + * + * @returns The browser UI language code such as en-US or fr-FR. + */ + getUILanguage(): string; + /** + * Detects the language of the provided text using CLD. + * + * @param text User input string to be translated. + */ + detectLanguage(text: string): Promise<DetectLanguageCallbackResultType>; + } + } + /** + * Namespace: browser.identity + */ + namespace Identity { + /** + * An object encapsulating an OAuth account id. + */ + interface AccountInfo { + /** + * A unique identifier for the account. This ID will not change for the lifetime of the account. + */ + id: string; + } + interface LaunchWebAuthFlowDetailsType { + url: Browser.Manifest.HttpURL; + /** + * Optional. + */ + interactive?: boolean; + } + interface Static { + /** + * Starts an auth flow at the specified URL. + */ + launchWebAuthFlow(details: LaunchWebAuthFlowDetailsType): Promise<string>; + /** + * Generates a redirect URL to be used in |launchWebAuthFlow|. + * + * @param path Optional. The path appended to the end of the generated URL. + */ + getRedirectURL(path?: string): Promise<string>; + } + } + /** + * Namespace: browser.idle + */ + namespace Idle { + type IdleState = "active" | "idle" | "locked"; + interface Static { + /** + * Returns "idle" if the user has not generated any input for a specified number of seconds, or "active" otherwise. + * + * @param detectionIntervalInSeconds The system is considered idle if detectionIntervalInSeconds seconds have elapsed since + * the last user input detected. + */ + queryState(detectionIntervalInSeconds: number): Promise<IdleState>; + /** + * Sets the interval, in seconds, used to determine when the system is in an idle state for onStateChanged events. + * The default interval is 60 seconds. + * + * @param intervalInSeconds Threshold, in seconds, used to determine when the system is in an idle state. + */ + setDetectionInterval(intervalInSeconds: number): void; + /** + * Fired when the system changes to an active or idle state. The event fires with "idle" if the the user has not generated + * any input for a specified number of seconds, and "active" when the user generates input on an idle system. + */ + onStateChanged: Events.Event<(newState: IdleState) => void>; + } + } + /** + * Namespace: browser.management + */ + namespace Management { + /** + * Information about an icon belonging to an extension. + */ + interface IconInfo { + /** + * A number representing the width and height of the icon. Likely values include (but are not limited to) 128, 48, 24, + * and 16. + */ + size: number; + /** + * The URL for this icon image. To display a grayscale version of the icon (to indicate that an extension is disabled, + * for example), append <code>?grayscale=true</code> to the URL. + */ + url: string; + } + /** + * A reason the item is disabled. + */ + type ExtensionDisabledReason = "unknown" | "permissions_increase"; + /** + * The type of this extension, 'extension' or 'theme'. + */ + type ExtensionType = "extension" | "theme"; + /** + * How the extension was installed. One of<br><var>development</var>: The extension was loaded unpacked in developer mode, + * <br><var>normal</var>: The extension was installed normally via an .xpi file,<br><var>sideload</var> + * : The extension was installed by other software on the machine,<br><var>admin</var> + * : The extension was installed by policy,<br><var>other</var>: The extension was installed by other means. + */ + type ExtensionInstallType = "development" | "normal" | "sideload" | "admin" | "other"; + /** + * Information about an installed extension. + */ + interface ExtensionInfo { + /** + * The extension's unique identifier. + */ + id: string; + /** + * The name of this extension. + */ + name: string; + /** + * A short version of the name of this extension. + * Optional. + */ + shortName?: string; + /** + * The description of this extension. + */ + description: string; + /** + * The <a href='manifest/version'>version</a> of this extension. + */ + version: string; + /** + * The <a href='manifest/version#version_name'>version name</a> of this extension if the manifest specified one. + * Optional. + */ + versionName?: string; + /** + * Whether this extension can be disabled or uninstalled by the user. + */ + mayDisable: boolean; + /** + * Whether it is currently enabled or disabled. + */ + enabled: boolean; + /** + * A reason the item is disabled. + * Optional. + */ + disabledReason?: ExtensionDisabledReason; + /** + * The type of this extension, 'extension' or 'theme'. + */ + type: ExtensionType; + /** + * The URL of the homepage of this extension. + * Optional. + */ + homepageUrl?: string; + /** + * The update URL of this extension. + * Optional. + */ + updateUrl?: string; + /** + * The url for the item's options page, if it has one. + */ + optionsUrl: string; + /** + * A list of icon information. Note that this just reflects what was declared in the manifest, + * and the actual image at that url may be larger or smaller than what was declared, + * so you might consider using explicit width and height attributes on img tags referencing these images. + * See the <a href='manifest/icons'>manifest documentation on icons</a> for more details. + * Optional. + */ + icons?: IconInfo[]; + /** + * Returns a list of API based permissions. + * Optional. + */ + permissions?: string[]; + /** + * Returns a list of host based permissions. + * Optional. + */ + hostPermissions?: string[]; + /** + * How the extension was installed. + */ + installType: ExtensionInstallType; + } + interface InstallOptionsType { + /** + * URL pointing to the XPI file on addons.mozilla.org or similar. + */ + url: Browser.Manifest.HttpURL; + /** + * A hash of the XPI file, using sha256 or stronger. + * Optional. + */ + hash?: string; + } + interface InstallCallbackResultType { + id: Browser.Manifest.ExtensionID; + } + interface UninstallSelfOptionsType { + /** + * Whether or not a confirm-uninstall dialog should prompt the user. Defaults to false. + * Optional. + */ + showConfirmDialog?: boolean; + /** + * The message to display to a user when being asked to confirm removal of the extension. + * Optional. + */ + dialogMessage?: string; + } + interface Static { + /** + * Returns a list of information about installed extensions. + */ + getAll(): Promise<ExtensionInfo[]>; + /** + * Returns information about the installed extension that has the given ID. + * + * @param id The ID from an item of $(ref:management.ExtensionInfo). + */ + get(id: Browser.Manifest.ExtensionID): Promise<ExtensionInfo>; + /** + * Installs and enables a theme extension from the given url. + */ + install(options: InstallOptionsType): Promise<InstallCallbackResultType>; + /** + * Returns information about the calling extension. Note: This function can be used without requesting the 'management' + * permission in the manifest. + */ + getSelf(): Promise<ExtensionInfo>; + /** + * Uninstalls the calling extension. Note: This function can be used without requesting the 'management' permission in the + * manifest. + * + * @param options Optional. + */ + uninstallSelf(options?: UninstallSelfOptionsType): Promise<void>; + /** + * Enables or disables the given add-on. + * + * @param id ID of the add-on to enable/disable. + * @param enabled Whether to enable or disable the add-on. + */ + setEnabled(id: string, enabled: boolean): Promise<void>; + /** + * Fired when an addon has been disabled. + */ + onDisabled: Events.Event<(info: ExtensionInfo) => void>; + /** + * Fired when an addon has been enabled. + */ + onEnabled: Events.Event<(info: ExtensionInfo) => void>; + /** + * Fired when an addon has been installed. + */ + onInstalled: Events.Event<(info: ExtensionInfo) => void>; + /** + * Fired when an addon has been uninstalled. + */ + onUninstalled: Events.Event<(info: ExtensionInfo) => void>; + } + } + /** + * Namespace: browser.manifest + */ + namespace Manifest { + /** + * Common properties for all manifest.json files + */ + interface ManifestBase { + manifest_version: number; + /** + * The applications property is deprecated, please use 'browser_specific_settings' + * Optional. + */ + applications?: DeprecatedApplications; + /** + * Optional. + */ + browser_specific_settings?: BrowserSpecificSettings; + /** + * Name must be at least 2, and should be at most 75 characters + */ + name: string; + /** + * Optional. + */ + short_name?: string; + /** + * Optional. + */ + description?: string; + /** + * Optional. + */ + author?: string; + version: string; + /** + * Optional. + */ + homepage_url?: string; + /** + * Optional. + */ + install_origins?: string[]; + /** + * Optional. + */ + developer?: ManifestBaseDeveloperType; + /** + * In addition to the version field, which is used for update purposes, version_name can be set to a descriptive version + * string and will be used for display purposes if present. If no version_name is present, + * the version field will be used for display purposes as well. + * Optional. + */ + version_name?: string; + } + /** + * Represents a WebExtension manifest.json file + */ + interface WebExtensionManifest extends ManifestBase { + /** + * Optional. + */ + minimum_chrome_version?: string; + /** + * Optional. + */ + minimum_opera_version?: string; + /** + * Optional. + */ + icons?: Record<string, ExtensionFileUrl>; + /** + * The 'split' value is not supported. + * Optional. + */ + incognito?: WebExtensionManifestIncognitoEnum; + /** + * Optional. + */ + background?: WebExtensionManifestBackgroundType; + /** + * Alias property for options_ui.page, ignored when options_ui.page is set. When using this property the options page is + * always opened in a new tab. + * Optional. + */ + options_page?: ExtensionURL; + /** + * Optional. + */ + options_ui?: WebExtensionManifestOptionsUiType; + /** + * Optional. + */ + content_scripts?: ContentScript[]; + /** + * Optional. + */ + content_security_policy?: string | WebExtensionManifestContentSecurityPolicyC2Type; + /** + * Optional. + */ + permissions?: PermissionOrOrigin[] | Permission[]; + /** + * Optional. + */ + granted_host_permissions?: boolean; + /** + * Optional. + */ + host_permissions?: MatchPattern[]; + /** + * Optional. + */ + optional_host_permissions?: MatchPattern[]; + /** + * Optional. + */ + optional_permissions?: OptionalPermissionOrOrigin[]; + /** + * Optional. + */ + web_accessible_resources?: string[] | WebExtensionManifestWebAccessibleResourcesC2ItemType[]; + /** + * Optional. + */ + hidden?: boolean; + /** + * Optional. + */ + action?: ActionManifest; + /** + * Optional. + */ + browser_action?: ActionManifest; + /** + * Optional. + */ + chrome_settings_overrides?: WebExtensionManifestChromeSettingsOverridesType; + /** + * Optional. + */ + commands?: Record<string, WebExtensionManifestCommandsType>; + /** + * Optional. + */ + declarative_net_request?: WebExtensionManifestDeclarativeNetRequestType; + /** + * Optional. + */ + devtools_page?: ExtensionURL; + /** + * Optional. + */ + experiment_apis?: WebExtensionManifestExperimentApisType; + /** + * A list of protocol handler definitions. + * Optional. + */ + protocol_handlers?: ProtocolHandler[]; + /** + * Optional. + */ + default_locale?: string; + /** + * Optional. + */ + l10n_resources?: string[]; + /** + * Optional. + */ + omnibox?: WebExtensionManifestOmniboxType; + /** + * Optional. + */ + page_action?: WebExtensionManifestPageActionType; + /** + * Optional. + */ + sidebar_action?: WebExtensionManifestSidebarActionType; + /** + * Optional. + */ + theme_experiment?: ThemeExperiment; + /** + * Optional. + */ + chrome_url_overrides?: WebExtensionManifestChromeUrlOverridesType; + /** + * Optional. + */ + user_scripts?: WebExtensionManifestUserScriptsType; + } + /** + * Represents a WebExtension language pack manifest.json file + */ + interface WebExtensionLangpackManifest extends ManifestBase { + langpack_id: string; + languages: Record<string, WebExtensionLangpackManifestLanguagesPatternType>; + /** + * Optional. + */ + sources?: Record<string, WebExtensionLangpackManifestSourcesPatternType>; + } + /** + * Represents a WebExtension dictionary manifest.json file + */ + interface WebExtensionDictionaryManifest extends ManifestBase { + dictionaries: Record<string, string>; + } + interface ThemeIcons { + /** + * A light icon to use for dark themes + */ + light: ExtensionURL; + /** + * The dark icon to use for light themes + */ + dark: ExtensionURL; + /** + * The size of the icons + */ + size: number; + } + type OptionalOnlyPermission = "trialML" | "userScripts"; + type OptionalPermissionNoPrompt = "idle" | "cookies" | "menus.overrideContext" | "scripting" | "search" | "tabGroups" | "activeTab" | "webRequest" | "webRequestAuthProvider" | "webRequestBlocking" | "webRequestFilterResponse" | "webRequestFilterResponse.serviceWorkerScript"; + type OptionalPermission = OptionalPermissionNoPrompt | "clipboardRead" | "clipboardWrite" | "geolocation" | "notifications" | "bookmarks" | "browserSettings" | "browsingData" | "declarativeNetRequestFeedback" | "devtools" | "downloads" | "downloads.open" | "find" | "history" | "management" | "pkcs11" | "privacy" | "proxy" | "nativeMessaging" | "sessions" | "tabs" | "tabHide" | "topSites" | "webNavigation" | "identity.email"; + type OptionalPermissionOrOrigin = OptionalPermission | OptionalOnlyPermission | MatchPattern; + type PermissionPrivileged = "mozillaAddons" | "activityLog" | "networkStatus" | "normandyAddonStudy"; + type CommonDataCollectionPermission = "authenticationInfo" | "bookmarksInfo" | "browsingActivity" | "financialAndPaymentInfo" | "healthInfo" | "locationInfo" | "personalCommunications" | "personallyIdentifyingInfo" | "searchTerms" | "websiteActivity" | "websiteContent"; + type DataCollectionPermission = CommonDataCollectionPermission | "none"; + type OptionalDataCollectionPermission = CommonDataCollectionPermission | "technicalAndInteraction"; + type PermissionNoPrompt = OptionalPermissionNoPrompt | PermissionPrivileged | "alarms" | "storage" | "unlimitedStorage" | "captivePortal" | "contextualIdentities" | "declarativeNetRequestWithHostAccess" | "dns" | "geckoProfiler" | "identity" | "menus" | "contextMenus" | "theme"; + type Permission = PermissionNoPrompt | OptionalPermission | "declarativeNetRequest" | string; + type PermissionOrOrigin = Permission | MatchPattern; + type HttpURL = string; + type ExtensionURL = string; + type ExtensionFileUrl = string; + type ImageDataOrExtensionURL = string; + type ExtensionID = string; + interface FirefoxSpecificProperties { + /** + * Optional. + */ + id?: ExtensionID; + /** + * Optional. + */ + update_url?: string; + /** + * Optional. + */ + strict_min_version?: string; + /** + * Optional. + */ + strict_max_version?: string; + /** + * Optional. + */ + admin_install_only?: boolean; + /** + * Optional. + */ + data_collection_permissions?: FirefoxSpecificPropertiesDataCollectionPermissionsType; + } + interface GeckoAndroidSpecificProperties { + /** + * Optional. + */ + strict_min_version?: string; + /** + * Optional. + */ + strict_max_version?: string; + } + interface DeprecatedApplications { + /** + * Optional. + */ + gecko?: FirefoxSpecificProperties; + } + interface BrowserSpecificSettings { + /** + * Optional. + */ + gecko?: FirefoxSpecificProperties; + /** + * Optional. + */ + gecko_android?: GeckoAndroidSpecificProperties; + } + type MatchPattern = "<all_urls>" | MatchPatternRestricted | MatchPatternUnestricted; + /** + * Same as MatchPattern above, but excludes <all_urls> + */ + type MatchPatternRestricted = string; + /** + * Mostly unrestricted match patterns for privileged add-ons. This should technically be rejected for unprivileged add-ons, + * but, reasons. The MatchPattern class will still refuse privileged schemes for those extensions. + */ + type MatchPatternUnestricted = string; + /** + * Details of the script or CSS to inject. Either the code or the file property must be set, + * but both may not be set at the same time. Based on InjectDetails, but using underscore rather than camel case naming + * conventions. + */ + interface ContentScript { + matches: MatchPattern[]; + /** + * Optional. + */ + exclude_matches?: MatchPattern[]; + /** + * Optional. + */ + include_globs?: string[]; + /** + * Optional. + */ + exclude_globs?: string[]; + /** + * The list of CSS files to inject + * Optional. + */ + css?: ExtensionURL[]; + /** + * The list of JS files to inject + * Optional. + */ + js?: ExtensionURL[]; + /** + * If allFrames is <code>true</code>, implies that the JavaScript or CSS should be injected into all frames of current page. + * By default, it's <code>false</code> and is only injected into the top frame. + * Optional. + */ + all_frames?: boolean; + /** + * If match_about_blank is true, then the code is also injected in about:blank and about:srcdoc frames if your extension + * has access to its parent document. Ignored if match_origin_as_fallback is specified. By default it is <code>false</code>. + * Optional. + */ + match_about_blank?: boolean; + /** + * If match_origin_as_fallback is true, then the code is also injected in about:, data:, + * blob: when their origin matches the pattern in 'matches', even if the actual document origin is opaque (due to the use + * of CSP sandbox or iframe sandbox). Match patterns in 'matches' must specify a wildcard path glob. By default it is <code> + * false</code>. + * Optional. + */ + match_origin_as_fallback?: boolean; + /** + * The soonest that the JavaScript or CSS will be injected into the tab. Defaults to "document_idle". + * Optional. + */ + run_at?: Browser.ExtensionTypes.RunAt; + /** + * The JavaScript world for a script to execute within. Defaults to "ISOLATED". + * Optional. + */ + world?: Browser.ExtensionTypes.ExecutionWorld; + } + type IconPath = Record<string, ExtensionFileUrl> | ExtensionFileUrl; + type IconImageData = Record<string, ImageData> | ImageData; + interface ActionManifest { + /** + * Optional. + */ + default_title?: string; + /** + * Optional. + */ + default_icon?: IconPath; + /** + * Specifies icons to use for dark and light themes + * Optional. + */ + theme_icons?: ThemeIcons[]; + /** + * Optional. + */ + default_popup?: string; + /** + * Deprecated in Manifest V3. + * Optional. + */ + browser_style?: boolean; + /** + * Defines the location the browserAction will appear by default. The default location is navbar. + * Optional. + */ + default_area?: ActionManifestDefaultAreaEnum; + } + type KeyName = string; + /** + * Represents a protocol handler definition. + */ + interface ProtocolHandler { + /** + * A user-readable title string for the protocol handler. This will be displayed to the user in interface objects as needed. + */ + name: string; + /** + * The protocol the site wishes to handle, specified as a string. For example, you can register to handle SMS text message + * links by registering to handle the "sms" scheme. + */ + protocol: "bitcoin" | "dat" | "dweb" | "ftp" | "geo" | "gopher" | "im" | "ipfs" | "ipns" | "irc" | "ircs" | "magnet" | "mailto" | "matrix" | "mms" | "news" | "nntp" | "sip" | "sms" | "smsto" | "ssb" | "ssh" | "tel" | "urn" | "webcal" | "wtai" | "xmpp" | string; + /** + * The URL of the handler, as a string. This string should include "%s" as a placeholder which will be replaced with the + * escaped URL of the document to be handled. This URL might be a true URL, or it could be a phone number, email address, + * or so forth. + */ + uriTemplate: ExtensionURL | HttpURL; + } + type ThemeColor = string | [ + number, + number, + number + ] | [ + number, + number, + number, + number + ]; + interface ThemeExperiment { + /** + * Optional. + */ + stylesheet?: ExtensionURL; + /** + * Optional. + */ + images?: ThemeExperimentImagesType; + /** + * Optional. + */ + colors?: ThemeExperimentColorsType; + /** + * Optional. + */ + properties?: ThemeExperimentPropertiesType; + } + interface ThemeType { + /** + * Optional. + */ + images?: ThemeTypeImagesType; + /** + * Optional. + */ + colors?: ThemeTypeColorsType; + /** + * Optional. + */ + properties?: ThemeTypePropertiesType; + } + /** + * Contents of manifest.json for a static theme + */ + interface ThemeManifest extends Browser.Manifest.ManifestBase { + theme: ThemeType; + /** + * Optional. + */ + dark_theme?: ThemeType; + /** + * Optional. + */ + default_locale?: string; + /** + * Optional. + */ + theme_experiment?: ThemeExperiment; + /** + * Optional. + */ + icons?: Record<string, string>; + } + interface ManifestBaseDeveloperType { + /** + * Optional. + */ + name?: string; + /** + * Optional. + */ + url?: string; + } + /** + * The 'split' value is not supported. + */ + type WebExtensionManifestIncognitoEnum = "not_allowed" | "spanning" | "split"; + /** + * Only supported for page/scripts; not for service_worker yet, see bug 1775574 + */ + type WebExtensionManifestBackgroundTypeEnum = "module" | "classic"; + type WebExtensionManifestBackgroundPreferredEnvironmentItemEnum = "service_worker" | "document"; + interface WebExtensionManifestBackgroundType { + /** + * Optional. + */ + service_worker?: ExtensionURL; + /** + * Optional. + */ + page?: ExtensionURL; + /** + * Optional. + */ + scripts?: ExtensionURL[]; + /** + * Only supported for page/scripts; not for service_worker yet, see bug 1775574 + * Optional. + */ + type?: WebExtensionManifestBackgroundTypeEnum; + /** + * Optional. + */ + persistent?: boolean; + /** + * Optional. + */ + preferred_environment?: WebExtensionManifestBackgroundPreferredEnvironmentItemEnum[]; + } + interface WebExtensionManifestOptionsUiType { + page: ExtensionURL; + /** + * Defaults to true in Manifest V2; Deprecated in Manifest V3. + * Optional. + */ + browser_style?: boolean; + /** + * chrome_style is ignored in Firefox. Its replacement (browser_style) has been deprecated. + * Optional. + */ + chrome_style?: boolean; + /** + * Optional. + */ + open_in_tab?: boolean; + } + interface WebExtensionManifestContentSecurityPolicyC2Type { + /** + * The Content Security Policy used for extension pages. + * Optional. + */ + extension_pages?: string; + /** + * In addition, Manifest V3 disallows certain CSP modifications for `extension_pages` that were permitted in Manifest V2. + * The `script-src`, `object-src`, and `worker-src` directives may only have the following values: + * - `self` + * - `none` - Any localhost source, (`http://localhost`, `http://127.0.0.1`, or any port on those domains) + * Optional. + */ + sandbox?: string; + } + interface WebExtensionManifestWebAccessibleResourcesC2ItemType { + resources: string[]; + /** + * Optional. + */ + matches?: MatchPattern[]; + /** + * Optional. + */ + extension_ids?: Array<ExtensionID | "*">; + } + interface WebExtensionManifestChromeSettingsOverridesSearchProviderType { + name: string; + /** + * Optional. + */ + keyword?: string | string[]; + search_url: string; + /** + * Optional. + */ + favicon_url?: string; + /** + * Optional. + */ + suggest_url?: string; + /** + * GET parameters to the search_url as a query string. + * Optional. + */ + search_url_get_params?: string; + /** + * POST parameters to the search_url as a query string. + * Optional. + */ + search_url_post_params?: string; + /** + * GET parameters to the suggest_url as a query string. + * Optional. + */ + suggest_url_get_params?: string; + /** + * POST parameters to the suggest_url as a query string. + * Optional. + */ + suggest_url_post_params?: string; + /** + * Encoding of the search term. + * Optional. + */ + encoding?: string; + /** + * Sets the default engine to a built-in engine only. + * Optional. + */ + is_default?: boolean; + } + interface WebExtensionManifestChromeSettingsOverridesType { + /** + * Optional. + */ + homepage?: string; + /** + * Optional. + */ + search_provider?: WebExtensionManifestChromeSettingsOverridesSearchProviderType; + } + interface WebExtensionManifestCommandsSuggestedKeyType { + /** + * Optional. + */ + default?: KeyName; + /** + * Optional. + */ + mac?: KeyName; + /** + * Optional. + */ + linux?: KeyName; + /** + * Optional. + */ + windows?: KeyName; + /** + * Optional. + */ + chromeos?: string; + /** + * Optional. + */ + android?: string; + /** + * Optional. + */ + ios?: string; + } + interface WebExtensionManifestCommandsType { + /** + * Optional. + */ + suggested_key?: WebExtensionManifestCommandsSuggestedKeyType; + /** + * Optional. + */ + description?: string; + } + interface WebExtensionManifestDeclarativeNetRequestRuleResourcesItemType { + /** + * A non-empty string uniquely identifying the ruleset. IDs beginning with '_' are reserved for internal use. + */ + id: string; + /** + * Whether the ruleset is enabled by default. + */ + enabled: boolean; + /** + * The path of the JSON ruleset relative to the extension directory. + */ + path: Browser.Manifest.ExtensionURL; + } + interface WebExtensionManifestDeclarativeNetRequestType { + rule_resources: WebExtensionManifestDeclarativeNetRequestRuleResourcesItemType[]; + } + interface WebExtensionManifestExperimentApisType { + [s: string]: Browser.Experiments.ExperimentAPI; + } + interface WebExtensionManifestOmniboxType { + keyword: string; + } + interface WebExtensionManifestPageActionType { + /** + * Optional. + */ + default_title?: string; + /** + * Optional. + */ + default_icon?: IconPath; + /** + * Optional. + */ + default_popup?: string; + /** + * Deprecated in Manifest V3. + * Optional. + */ + browser_style?: boolean; + /** + * Optional. + */ + show_matches?: MatchPattern[]; + /** + * Optional. + */ + hide_matches?: MatchPatternRestricted[]; + /** + * Optional. + */ + pinned?: boolean; + } + interface WebExtensionManifestSidebarActionType { + /** + * Optional. + */ + default_title?: string; + /** + * Optional. + */ + default_icon?: IconPath; + /** + * Defaults to true in Manifest V2; Deprecated in Manifest V3. + * Optional. + */ + browser_style?: boolean; + default_panel: string; + /** + * Whether or not the sidebar is opened at install. Default is <code>true</code>. + * Optional. + */ + open_at_install?: boolean; + } + interface WebExtensionManifestChromeUrlOverridesType { + /** + * Optional. + */ + newtab?: ExtensionURL; + } + interface WebExtensionManifestUserScriptsType { + /** + * Optional. + */ + api_script?: Browser.Manifest.ExtensionURL; + } + interface WebExtensionLangpackManifestLanguagesPatternType { + chrome_resources: Record<string, ExtensionURL | Record<string, ExtensionURL>>; + version: string; + } + interface WebExtensionLangpackManifestSourcesPatternType { + base_path: ExtensionURL; + /** + * Optional. + */ + paths?: string[]; + } + interface FirefoxSpecificPropertiesDataCollectionPermissionsType { + /** + * Optional. + */ + required?: DataCollectionPermission[]; + /** + * Optional. + */ + optional?: OptionalDataCollectionPermission[]; + } + /** + * Defines the location the browserAction will appear by default. The default location is navbar. + */ + type ActionManifestDefaultAreaEnum = "navbar" | "menupanel" | "tabstrip" | "personaltoolbar"; + interface ThemeExperimentImagesType { + [s: string]: unknown; + } + interface ThemeExperimentColorsType { + [s: string]: unknown; + } + interface ThemeExperimentPropertiesType { + [s: string]: unknown; + } + interface ThemeTypeImagesType { + /** + * Optional. + */ + additional_backgrounds?: ImageDataOrExtensionURL[]; + /** + * Optional. + */ + theme_frame?: ImageDataOrExtensionURL; + } + interface ThemeTypeColorsType { + /** + * Optional. + */ + tab_selected?: ThemeColor; + /** + * Optional. + */ + frame?: ThemeColor; + /** + * Optional. + */ + frame_inactive?: ThemeColor; + /** + * Optional. + */ + tab_background_text?: ThemeColor; + /** + * Optional. + */ + tab_background_separator?: ThemeColor; + /** + * Optional. + */ + tab_loading?: ThemeColor; + /** + * Optional. + */ + tab_text?: ThemeColor; + /** + * Optional. + */ + tab_line?: ThemeColor; + /** + * Optional. + */ + toolbar?: ThemeColor; + /** + * This color property is an alias of 'bookmark_text'. + * Optional. + */ + toolbar_text?: ThemeColor; + /** + * Optional. + */ + bookmark_text?: ThemeColor; + /** + * Optional. + */ + toolbar_field?: ThemeColor; + /** + * Optional. + */ + toolbar_field_text?: ThemeColor; + /** + * Optional. + */ + toolbar_field_border?: ThemeColor; + /** + * Optional. + */ + toolbar_top_separator?: ThemeColor; + /** + * Optional. + */ + toolbar_bottom_separator?: ThemeColor; + /** + * Optional. + */ + toolbar_vertical_separator?: ThemeColor; + /** + * Optional. + */ + icons?: ThemeColor; + /** + * Optional. + */ + icons_attention?: ThemeColor; + /** + * Optional. + */ + button_background_hover?: ThemeColor; + /** + * Optional. + */ + button_background_active?: ThemeColor; + /** + * Optional. + */ + popup?: ThemeColor; + /** + * Optional. + */ + popup_text?: ThemeColor; + /** + * Optional. + */ + popup_border?: ThemeColor; + /** + * Optional. + */ + toolbar_field_focus?: ThemeColor; + /** + * Optional. + */ + toolbar_field_text_focus?: ThemeColor; + /** + * Optional. + */ + toolbar_field_border_focus?: ThemeColor; + /** + * Optional. + */ + popup_highlight?: ThemeColor; + /** + * Optional. + */ + popup_highlight_text?: ThemeColor; + /** + * Optional. + */ + ntp_background?: ThemeColor; + /** + * Optional. + */ + ntp_card_background?: ThemeColor; + /** + * Optional. + */ + ntp_text?: ThemeColor; + /** + * Optional. + */ + sidebar?: ThemeColor; + /** + * Optional. + */ + sidebar_border?: ThemeColor; + /** + * Optional. + */ + sidebar_text?: ThemeColor; + /** + * Optional. + */ + sidebar_highlight?: ThemeColor; + /** + * Optional. + */ + sidebar_highlight_text?: ThemeColor; + /** + * Optional. + */ + toolbar_field_highlight?: ThemeColor; + /** + * Optional. + */ + toolbar_field_highlight_text?: ThemeColor; + } + type ThemeTypePropertiesAdditionalBackgroundsAlignmentItemEnum = "bottom" | "center" | "left" | "right" | "top" | "center bottom" | "center center" | "center top" | "left bottom" | "left center" | "left top" | "right bottom" | "right center" | "right top"; + type ThemeTypePropertiesAdditionalBackgroundsTilingItemEnum = "no-repeat" | "repeat" | "repeat-x" | "repeat-y"; + type ThemeTypePropertiesColorSchemeEnum = "auto" | "light" | "dark" | "system"; + type ThemeTypePropertiesContentColorSchemeEnum = "auto" | "light" | "dark" | "system"; + interface ThemeTypePropertiesType { + /** + * Optional. + */ + additional_backgrounds_alignment?: ThemeTypePropertiesAdditionalBackgroundsAlignmentItemEnum[]; + /** + * Optional. + */ + additional_backgrounds_tiling?: ThemeTypePropertiesAdditionalBackgroundsTilingItemEnum[]; + /** + * Optional. + */ + color_scheme?: ThemeTypePropertiesColorSchemeEnum; + /** + * Optional. + */ + content_color_scheme?: ThemeTypePropertiesContentColorSchemeEnum; + } + interface Static { + [s: string]: unknown; + } + } + /** + * Namespace: browser.contextMenus + */ + namespace ContextMenus { + interface Static extends Menus.Static { + [s: string]: unknown; + } + } + /** + * Namespace: browser.menus + */ + namespace Menus { + /** + * The different contexts a menu can appear in. Specifying 'all' is equivalent to the combination of all other contexts + * except for 'tab' and 'tools_menu'. + */ + type ContextType = "all" | "page" | "frame" | "selection" | "link" | "editable" | "password" | "image" | "video" | "audio" | "launcher" | "bookmark" | "page_action" | "tab" | "tools_menu" | "browser_action" | "action"; + /** + * The type of menu item. + */ + type ItemType = "normal" | "checkbox" | "radio" | "separator"; + /** + * Information sent when a context menu item is clicked. + */ + interface OnClickData { + /** + * The ID of the menu item that was clicked. + */ + menuItemId: number | string; + /** + * The parent ID, if any, for the item clicked. + * Optional. + */ + parentMenuItemId?: number | string; + /** + * The type of view where the menu is clicked. May be unset if the menu is not associated with a view. + * Optional. + */ + viewType?: Browser.Extension.ViewType; + /** + * One of 'image', 'video', or 'audio' if the context menu was activated on one of these types of elements. + * Optional. + */ + mediaType?: string; + /** + * If the element is a link, the text of that link. + * Optional. + */ + linkText?: string; + /** + * If the element is a link, the URL it points to. + * Optional. + */ + linkUrl?: string; + /** + * Will be present for elements with a 'src' URL. + * Optional. + */ + srcUrl?: string; + /** + * The URL of the page where the menu item was clicked. This property is not set if the click occured in a context where + * there is no current page, such as in a launcher context menu. + * Optional. + */ + pageUrl?: string; + /** + * The id of the frame of the element where the context menu was clicked. + * Optional. + */ + frameId?: number; + /** + * The URL of the frame of the element where the context menu was clicked, if it was in a frame. + * Optional. + */ + frameUrl?: string; + /** + * The text for the context selection, if any. + * Optional. + */ + selectionText?: string; + /** + * A flag indicating whether the element is editable (text input, textarea, etc.). + */ + editable: boolean; + /** + * A flag indicating the state of a checkbox or radio item before it was clicked. + * Optional. + */ + wasChecked?: boolean; + /** + * A flag indicating the state of a checkbox or radio item after it is clicked. + * Optional. + */ + checked?: boolean; + /** + * The id of the bookmark where the context menu was clicked, if it was on a bookmark. + * Optional. + */ + bookmarkId?: string; + /** + * An array of keyboard modifiers that were held while the menu item was clicked. + */ + modifiers: OnClickDataModifiersItemEnum[]; + /** + * An integer value of button by which menu item was clicked. + * Optional. + */ + button?: number; + /** + * An identifier of the clicked element, if any. Use menus.getTargetElement in the page to find the corresponding element. + * Optional. + */ + targetElementId?: number; + } + interface CreateCreatePropertiesType { + /** + * The type of menu item. Defaults to 'normal' if not specified. + * Optional. + */ + type?: ItemType; + /** + * The unique ID to assign to this item. Mandatory for event pages. Cannot be the same as another ID for this extension. + * Optional. + */ + id?: string; + /** + * Optional. + */ + icons?: Record<string, string>; + /** + * The text to be displayed in the item; this is <em>required</em> unless <code>type</code> is 'separator'. + * When the context is 'selection', you can use <code>%s</code> within the string to show the selected text. For example, + * if this parameter's value is "Translate '%s' to Pig Latin" and the user selects the word "cool", + * the context menu item for the selection is "Translate 'cool' to Pig Latin". + * Optional. + */ + title?: string; + /** + * The initial state of a checkbox or radio item: true for selected and false for unselected. + * Only one radio item can be selected at a time in a given group of radio items. + * Optional. + */ + checked?: boolean; + /** + * List of contexts this menu item will appear in. Defaults to ['page'] if not specified. + * Optional. + */ + contexts?: ContextType[]; + /** + * List of view types where the menu item will be shown. Defaults to any view, including those without a viewType. + * Optional. + */ + viewTypes?: Browser.Extension.ViewType[]; + /** + * Whether the item is visible in the menu. + * Optional. + */ + visible?: boolean; + /** + * A function that will be called back when the menu item is clicked. Event pages cannot use this; instead, + * they should register a listener for $(ref:contextMenus.onClicked). + * + * @param info Information about the item clicked and the context where the click happened. + * @param tab The details of the tab where the click took place. Note: this parameter only present for extensions. + */ + onclick?(info: OnClickData, tab: Browser.Tabs.Tab): void; + /** + * The ID of a parent menu item; this makes the item a child of a previously added item. + * Optional. + */ + parentId?: number | string; + /** + * Lets you restrict the item to apply only to documents whose URL matches one of the given patterns. + * (This applies to frames as well.) For details on the format of a pattern, see $(topic:match_patterns)[Match Patterns]. + * Optional. + */ + documentUrlPatterns?: string[]; + /** + * Similar to documentUrlPatterns, but lets you filter based on the src attribute of img/audio/video tags and the href of + * anchor tags. + * Optional. + */ + targetUrlPatterns?: string[]; + /** + * Whether this context menu item is enabled or disabled. Defaults to true. + * Optional. + */ + enabled?: boolean; + /** + * Specifies a command to issue for the context click. + * Optional. + */ + command?: string | "_execute_browser_action" | "_execute_page_action" | "_execute_sidebar_action" | "_execute_action" | "_execute_page_action" | "_execute_sidebar_action"; + } + /** + * The properties to update. Accepts the same values as the create function. + */ + interface UpdateUpdatePropertiesType { + /** + * Optional. + */ + type?: ItemType; + /** + * Optional. + */ + icons?: Record<string, string>; + /** + * Optional. + */ + title?: string; + /** + * Optional. + */ + checked?: boolean; + /** + * Optional. + */ + contexts?: ContextType[]; + /** + * Optional. + */ + viewTypes?: Browser.Extension.ViewType[]; + /** + * Whether the item is visible in the menu. + * Optional. + */ + visible?: boolean; + /** + * @param tab The details of the tab where the click took place. Note: this parameter only present for extensions. + */ + onclick?(info: OnClickData, tab: Browser.Tabs.Tab): void; + /** + * Note: You cannot change an item to be a child of one of its own descendants. + * Optional. + */ + parentId?: number | string; + /** + * Optional. + */ + documentUrlPatterns?: string[]; + /** + * Optional. + */ + targetUrlPatterns?: string[]; + /** + * Optional. + */ + enabled?: boolean; + } + interface OverrideContextContextOptionsType { + /** + * Whether to also include default menu items in the menu. + * Optional. + */ + showDefaults?: boolean; + /** + * ContextType to override, to allow menu items from other extensions in the menu. Currently only 'bookmark' and 'tab' are + * supported. showDefaults cannot be used with this option. + * Optional. + */ + context?: OverrideContextContextOptionsTypeContextEnum; + /** + * Required when context is 'bookmark'. Requires 'bookmark' permission. + * Optional. + */ + bookmarkId?: string; + /** + * Required when context is 'tab'. Requires 'tabs' permission. + * Optional. + */ + tabId?: number; + } + /** + * Information about the context of the menu action and the created menu items. For more information about each property, + * see OnClickData. The following properties are only set if the extension has host permissions for the given context: + * linkUrl, linkText, srcUrl, pageUrl, frameUrl, selectionText. + */ + interface OnShownInfoType { + /** + * A list of IDs of the menu items that were shown. + */ + menuIds: Array<number | string>; + /** + * A list of all contexts that apply to the menu. + */ + contexts: ContextType[]; + /** + * Optional. + */ + viewType?: Browser.Extension.ViewType; + editable: boolean; + /** + * Optional. + */ + mediaType?: string; + /** + * Optional. + */ + linkUrl?: string; + /** + * Optional. + */ + linkText?: string; + /** + * Optional. + */ + srcUrl?: string; + /** + * Optional. + */ + pageUrl?: string; + /** + * Optional. + */ + frameUrl?: string; + /** + * Optional. + */ + selectionText?: string; + /** + * Optional. + */ + targetElementId?: number; + } + type OnClickDataModifiersItemEnum = "Shift" | "Alt" | "Command" | "Ctrl" | "MacCtrl"; + /** + * ContextType to override, to allow menu items from other extensions in the menu. Currently only 'bookmark' and 'tab' are + * supported. showDefaults cannot be used with this option. + */ + type OverrideContextContextOptionsTypeContextEnum = "bookmark" | "tab"; + interface Static { + /** + * Creates a new context menu item. Note that if an error occurs during creation, you may not find out until the creation + * callback fires (the details will be in $(ref:runtime.lastError)). + * + * @param callback Optional. Called when the item has been created in the browser. If there were any problems creating the + * item, details will be available in $(ref:runtime.lastError). + * @returns The ID of the newly created item. + */ + create(createProperties: CreateCreatePropertiesType, callback?: () => void): number | string; + /** + * Updates a previously created context menu item. + * + * @param id The ID of the item to update. + * @param updateProperties The properties to update. Accepts the same values as the create function. + * @returns Called when the context menu has been updated. + */ + update(id: number | string, updateProperties: UpdateUpdatePropertiesType): Promise<void>; + /** + * Removes a context menu item. + * + * @param menuItemId The ID of the context menu item to remove. + * @returns Called when the context menu has been removed. + */ + remove(menuItemId: number | string): Promise<void>; + /** + * Removes all context menu items added by this extension. + * + * @returns Called when removal is complete. + */ + removeAll(): Promise<void>; + /** + * Show the matching menu items from this extension instead of the default menu. This should be called during a + * 'contextmenu' DOM event handler, and only applies to the menu that opens after this event. + */ + overrideContext(contextOptions: OverrideContextContextOptionsType): void; + /** + * Updates the extension items in the shown menu, including changes that have been made since the menu was shown. + * Has no effect if the menu is hidden. Rebuilding a shown menu is an expensive operation, + * only invoke this method when necessary. + */ + refresh(): Promise<void>; + /** + * Retrieve the element that was associated with a recent contextmenu event. + * + * @param targetElementId The identifier of the clicked element, available as info.targetElementId in the menus.onShown, + * onClicked or onclick event. + */ + getTargetElement(targetElementId: number): Element; + /** + * Fired when a context menu item is clicked. + * + * @param info Information about the item clicked and the context where the click happened. + * @param tab Optional. The details of the tab where the click took place. If the click did not take place in a tab, + * this parameter will be missing. + */ + onClicked: Events.Event<(info: OnClickData, tab: Browser.Tabs.Tab | undefined) => void>; + /** + * Fired when a menu is shown. The extension can add, modify or remove menu items and call menus.refresh() + * to update the menu. + * + * @param info Information about the context of the menu action and the created menu items. + * For more information about each property, see OnClickData. The following properties are only set if the extension has + * host permissions for the given context: linkUrl, linkText, srcUrl, pageUrl, frameUrl, selectionText. + * @param tab The details of the tab where the menu was opened. + */ + onShown: Events.Event<(info: OnShownInfoType, tab: Browser.Tabs.Tab) => void>; + /** + * Fired when a menu is hidden. This event is only fired if onShown has fired before. + */ + onHidden: Events.Event<() => void>; + /** + * The maximum number of top level extension items that can be added to an extension action context menu. + * Any items beyond this limit will be ignored. + */ + ACTION_MENU_TOP_LEVEL_LIMIT: 6; + } + } + /** + * Namespace: browser.networkStatus + */ + namespace NetworkStatus { + interface NetworkLinkInfo { + /** + * Status of the network link, if "unknown" then link is usually assumed to be "up" + */ + status: NetworkLinkInfoStatusEnum; + /** + * If known, the type of network connection that is avialable. + */ + type: NetworkLinkInfoTypeEnum; + /** + * If known, the network id or name. + * Optional. + */ + id?: string; + } + /** + * Status of the network link, if "unknown" then link is usually assumed to be "up" + */ + type NetworkLinkInfoStatusEnum = "unknown" | "up" | "down"; + /** + * If known, the type of network connection that is avialable. + */ + type NetworkLinkInfoTypeEnum = "unknown" | "ethernet" | "usb" | "wifi" | "wimax" | "mobile"; + interface Static { + /** + * Returns the $(ref:NetworkLinkInfo) of the current network connection. + */ + getLinkInfo(): void; + /** + * Fired when the network connection state changes. + */ + onConnectionChanged: Events.Event<(details: NetworkLinkInfo) => void>; + } + } + /** + * Namespace: browser.normandyAddonStudy + */ + namespace NormandyAddonStudy { + interface Study { + /** + * The ID of the recipe for the study. + */ + recipeId: number; + /** + * A slug to identify the study. + */ + slug: string; + /** + * The name presented on about:studies. + */ + userFacingName: string; + /** + * The description presented on about:studies. + */ + userFacingDescription: string; + /** + * The study branch in which the user is enrolled. + */ + branch: string; + /** + * The state of the study. + */ + active: boolean; + /** + * The ID of the extension installed by the study. + */ + addonId: string; + /** + * The URL of the XPI that was downloaded and installed by the study. + */ + addonUrl: string; + /** + * The version of the extension installed by the study. + */ + addonVersion: string; + /** + * The start date for the study. + */ + studyStartDate: ExtensionTypes.DateType; + /** + * The end date for the study. + */ + studyEndDate: ExtensionTypes.DateType; + /** + * The record ID for the extension in Normandy server's database. + */ + extensionApiId: number; + /** + * A hash of the extension XPI file. + */ + extensionHash: string; + /** + * The algorithm used to hash the extension XPI file. + */ + extensionHashAlgorithm: string; + } + interface Static { + /** + * Returns a study object for the current study. + */ + getStudy(): void; + /** + * Marks the study as ended and then uninstalls the addon. + * + * @param reason The reason why the study is ending. + */ + endStudy(reason: string): void; + /** + * Returns an object with metadata about the client which may be required for constructing survey URLs. + */ + getClientMetadata(): void; + /** + * Fired when a user unenrolls from a study but before the addon is uninstalled. + * + * @param reason The reason why the study is ending. + */ + onUnenroll: Events.Event<(reason: string) => void>; + } + } + /** + * Namespace: browser.notifications + */ + namespace Notifications { + type TemplateType = "basic" | "image" | "list" | "progress"; + type PermissionLevel = "granted" | "denied"; + interface NotificationItem { + /** + * Title of one item of a list notification. + */ + title: string; + /** + * Additional details about this item. + */ + message: string; + } + interface CreateNotificationOptions { + /** + * Which type of notification to display. + */ + type: TemplateType; + /** + * A URL to the sender's avatar, app icon, or a thumbnail for image notifications. + * Optional. + */ + iconUrl?: string; + /** + * A URL to the app icon mask. + * Optional. + */ + appIconMaskUrl?: string; + /** + * Title of the notification (e.g. sender name for email). + */ + title: string; + /** + * Main notification content. + */ + message: string; + /** + * Alternate notification content with a lower-weight font. + * Optional. + */ + contextMessage?: string; + /** + * Priority ranges from -2 to 2. -2 is lowest priority. 2 is highest. Zero is default. + * Optional. + */ + priority?: number; + /** + * A timestamp associated with the notification, in milliseconds past the epoch. + * Optional. + */ + eventTime?: number; + /** + * A URL to the image thumbnail for image-type notifications. + * Optional. + */ + imageUrl?: string; + /** + * Items for multi-item notifications. + * Optional. + */ + items?: NotificationItem[]; + /** + * Current progress ranges from 0 to 100. + * Optional. + */ + progress?: number; + /** + * Whether to show UI indicating that the app will visibly respond to clicks on the body of a notification. + * Optional. + */ + isClickable?: boolean; + } + interface UpdateNotificationOptions { + /** + * Which type of notification to display. + * Optional. + */ + type?: TemplateType; + /** + * A URL to the sender's avatar, app icon, or a thumbnail for image notifications. + * Optional. + */ + iconUrl?: string; + /** + * A URL to the app icon mask. + * Optional. + */ + appIconMaskUrl?: string; + /** + * Title of the notification (e.g. sender name for email). + * Optional. + */ + title?: string; + /** + * Main notification content. + * Optional. + */ + message?: string; + /** + * Alternate notification content with a lower-weight font. + * Optional. + */ + contextMessage?: string; + /** + * Priority ranges from -2 to 2. -2 is lowest priority. 2 is highest. Zero is default. + * Optional. + */ + priority?: number; + /** + * A timestamp associated with the notification, in milliseconds past the epoch. + * Optional. + */ + eventTime?: number; + /** + * A URL to the image thumbnail for image-type notifications. + * Optional. + */ + imageUrl?: string; + /** + * Items for multi-item notifications. + * Optional. + */ + items?: NotificationItem[]; + /** + * Current progress ranges from 0 to 100. + * Optional. + */ + progress?: number; + /** + * Whether to show UI indicating that the app will visibly respond to clicks on the body of a notification. + * Optional. + */ + isClickable?: boolean; + } + interface Static { + /** + * Creates and displays a notification. + * + * @param notificationId Optional. Identifier of the notification. If it is empty, this method generates an id. + * If it matches an existing notification, this method first clears that notification before proceeding with the create + * operation. + * @param options Contents of the notification. + */ + create(notificationId: string | undefined, options: CreateNotificationOptions): Promise<string>; + /** + * Creates and displays a notification. + * + * @param options Contents of the notification. + */ + create(options: CreateNotificationOptions): Promise<string>; + /** + * Clears an existing notification. + * + * @param notificationId The id of the notification to be updated. + */ + clear(notificationId: string): Promise<boolean>; + /** + * Retrieves all the notifications. + */ + getAll(): Promise<Record<string, CreateNotificationOptions>>; + /** + * Fired when the notification closed, either by the system or by user action. + * + * @param notificationId The notificationId of the closed notification. + * @param byUser True if the notification was closed by the user. + */ + onClosed: Events.Event<(notificationId: string, byUser: boolean) => void>; + /** + * Fired when the user clicked in a non-button area of the notification. + * + * @param notificationId The notificationId of the clicked notification. + */ + onClicked: Events.Event<(notificationId: string) => void>; + /** + * Fired when the user pressed a button in the notification. + * + * @param notificationId The notificationId of the clicked notification. + * @param buttonIndex The index of the button clicked by the user. + */ + onButtonClicked: Events.Event<(notificationId: string, buttonIndex: number) => void>; + /** + * Fired when the notification is shown. + * + * @param notificationId The notificationId of the shown notification. + */ + onShown: Events.Event<(notificationId: string) => void>; + } + } + /** + * Namespace: browser.omnibox + */ + namespace Omnibox { + /** + * The style type. + */ + type DescriptionStyleType = "url" | "match" | "dim"; + /** + * The window disposition for the omnibox query. This is the recommended context to display results. For example, + * if the omnibox command is to navigate to a certain URL, a disposition of 'newForegroundTab' means the navigation should + * take place in a new selected tab. + */ + type OnInputEnteredDisposition = "currentTab" | "newForegroundTab" | "newBackgroundTab"; + /** + * A suggest result. + */ + interface SuggestResult { + /** + * The text that is put into the URL bar, and that is sent to the extension when the user chooses this entry. + */ + content: string; + /** + * The text that is displayed in the URL dropdown. Can contain XML-style markup for styling. + * The supported tags are 'url' (for a literal URL), 'match' (for highlighting text that matched what the user's query), + * and 'dim' (for dim helper text). The styles can be nested, eg. <dim><match>dimmed match</match></dim>. + * You must escape the five predefined entities to display them as text: stackoverflow.com/a/1091953/89484 + */ + description: string; + /** + * Whether the suggest result can be deleted by the user. + * Optional. + */ + deletable?: boolean; + } + /** + * A suggest result. + */ + interface DefaultSuggestResult { + /** + * The text that is displayed in the URL dropdown. + */ + description: string; + } + interface Static { + /** + * Sets the description and styling for the default suggestion. The default suggestion is the text that is displayed in the + * first suggestion row underneath the URL bar. + * + * @param suggestion A partial SuggestResult object, without the 'content' parameter. + */ + setDefaultSuggestion(suggestion: DefaultSuggestResult): void; + /** + * User has started a keyword input session by typing the extension's keyword. This is guaranteed to be sent exactly once + * per input session, and before any onInputChanged events. + */ + onInputStarted: Events.Event<() => void>; + /** + * User has changed what is typed into the omnibox. + * + * @param suggest A callback passed to the onInputChanged event used for sending suggestions back to the browser. + */ + onInputChanged: Events.Event<(text: string, suggest: (suggestResults: SuggestResult[]) => void) => void>; + /** + * User has accepted what is typed into the omnibox. + */ + onInputEntered: Events.Event<(text: string, disposition: OnInputEnteredDisposition) => void>; + /** + * User has ended the keyword input session without accepting the input. + */ + onInputCancelled: Events.Event<() => void>; + /** + * User has deleted a suggested result. + */ + onDeleteSuggestion: Events.Event<(text: string) => void>; + } + } + /** + * Namespace: browser.pageAction + */ + namespace PageAction { + /** + * Pixel data for an image. Must be an ImageData object (for example, from a <code>canvas</code> element). + */ + interface ImageDataType extends ImageData { + [s: string]: unknown; + } + /** + * Information sent when a page action is clicked. + */ + interface OnClickData { + /** + * An array of keyboard modifiers that were held while the menu item was clicked. + */ + modifiers: OnClickDataModifiersItemEnum[]; + /** + * An integer value of button by which menu item was clicked. + * Optional. + */ + button?: number; + } + interface IsShownDetailsType { + /** + * Specify the tab to get the shownness from. + */ + tabId: number; + } + interface SetTitleDetailsType { + /** + * The id of the tab for which you want to modify the page action. + */ + tabId: number; + /** + * The tooltip string. + */ + title: string | null; + } + interface GetTitleDetailsType { + /** + * Specify the tab to get the title from. + */ + tabId: number; + } + interface SetIconDetailsType { + /** + * The id of the tab for which you want to modify the page action. + */ + tabId: number; + /** + * Either an ImageData object or a dictionary {size -> ImageData} representing icon to be set. + * If the icon is specified as a dictionary, the actual image to be used is chosen depending on screen's pixel density. + * If the number of image pixels that fit into one screen space unit equals <code>scale</code>, then image with size <code> + * scale</code> * 19 will be selected. Initially only scales 1 and 2 will be supported. + * At least one image must be specified. Note that 'details.imageData = foo' is equivalent to 'details. + * imageData = {'19': foo}' + * Optional. + */ + imageData?: ImageDataType | Record<string, ImageDataType>; + /** + * Either a relative image path or a dictionary {size -> relative image path} pointing to icon to be set. + * If the icon is specified as a dictionary, the actual image to be used is chosen depending on screen's pixel density. + * If the number of image pixels that fit into one screen space unit equals <code>scale</code>, then image with size <code> + * scale</code> * 19 will be selected. Initially only scales 1 and 2 will be supported. + * At least one image must be specified. Note that 'details.path = foo' is equivalent to 'details.imageData = {'19': foo}' + * Optional. + */ + path?: string | Record<string, string>; + } + interface SetPopupDetailsType { + /** + * The id of the tab for which you want to modify the page action. + */ + tabId: number; + /** + * The html file to show in a popup. If set to the empty string (''), no popup is shown. + */ + popup: string | null; + } + interface GetPopupDetailsType { + /** + * Specify the tab to get the popup from. + */ + tabId: number; + } + type OnClickDataModifiersItemEnum = "Shift" | "Alt" | "Command" | "Ctrl" | "MacCtrl"; + interface Static { + /** + * Shows the page action. The page action is shown whenever the tab is selected. + * + * @param tabId The id of the tab for which you want to modify the page action. + */ + show(tabId: number): Promise<void>; + /** + * Hides the page action. + * + * @param tabId The id of the tab for which you want to modify the page action. + */ + hide(tabId: number): Promise<void>; + /** + * Checks whether the page action is shown. + */ + isShown(details: IsShownDetailsType): Promise<boolean>; + /** + * Sets the title of the page action. This is displayed in a tooltip over the page action. + */ + setTitle(details: SetTitleDetailsType): void; + /** + * Gets the title of the page action. + */ + getTitle(details: GetTitleDetailsType): Promise<string>; + /** + * Sets the icon for the page action. The icon can be specified either as the path to an image file or as the pixel data + * from a canvas element, or as dictionary of either one of those. Either the <b>path</b> or the <b>imageData</b> + * property must be specified. + */ + setIcon(details: SetIconDetailsType): Promise<void>; + /** + * Sets the html document to be opened as a popup when the user clicks on the page action's icon. + */ + setPopup(details: SetPopupDetailsType): Promise<void>; + /** + * Gets the html document set as the popup for this page action. + */ + getPopup(details: GetPopupDetailsType): Promise<string>; + /** + * Opens the extension page action in the active window. + */ + openPopup(): Promise<void>; + /** + * Fired when a page action icon is clicked. This event will not fire if the page action has a popup. + * + * @param info Optional. + */ + onClicked: Events.Event<(tab: Browser.Tabs.Tab, info: OnClickData | undefined) => void>; + } + } + /** + * Namespace: browser.permissions + */ + namespace Permissions { + interface Permissions { + /** + * Optional. + */ + permissions?: Array<Browser.Manifest.OptionalPermission | Browser.Manifest.OptionalOnlyPermission>; + /** + * Optional. + */ + origins?: Browser.Manifest.MatchPattern[]; + /** + * Optional. + */ + data_collection?: Browser.Manifest.OptionalDataCollectionPermission[]; + } + interface AnyPermissions { + /** + * Optional. + */ + permissions?: Array<Browser.Manifest.Permission | Browser.Manifest.OptionalOnlyPermission>; + /** + * Optional. + */ + origins?: Browser.Manifest.MatchPattern[]; + /** + * Optional. + */ + data_collection?: Browser.Manifest.OptionalDataCollectionPermission[]; + } + interface Static { + /** + * Get a list of all the extension's permissions. + */ + getAll(): Promise<AnyPermissions>; + /** + * Check if the extension has the given permissions. + */ + contains(permissions: AnyPermissions): Promise<boolean>; + /** + * Request the given permissions. + */ + request(permissions: Permissions): Promise<boolean>; + /** + * Relinquish the given permissions. + */ + remove(permissions: Permissions): Promise<boolean>; + /** + * Fired when the extension acquires new permissions. + */ + onAdded: Events.Event<(permissions: Permissions) => void>; + /** + * Fired when permissions are removed from the extension. + */ + onRemoved: Events.Event<(permissions: Permissions) => void>; + } + } + /** + * Namespace: browser.pkcs11 + */ + namespace Pkcs11 { + interface Token { + /** + * Name of the token. + */ + name: string; + /** + * Name of the token's manufacturer. + */ + manufacturer: string; + /** + * Hardware version, as a PKCS #11 version number (two 32-bit integers separated with a dot, like "1.0". + */ + HWVersion: string; + /** + * Firmware version, as a PKCS #11 version number (two 32-bit integers separated with a dot, like "1.0". + */ + FWVersion: string; + /** + * Serial number, whose format is defined by the token specification. + */ + serial: string; + /** + * true if the token is logged on already, false otherwise. + */ + isLoggedIn: boolean; + } + interface ModuleSlot { + /** + * The name of the slot. + */ + name: string; + /** + * The token of the slot. + */ + token: Token | null; + } + interface Static { + /** + * checks whether a PKCS#11 module, given by name, is installed + */ + isModuleInstalled(name: string): Promise<boolean>; + /** + * Install a PKCS#11 module with a given name + * + * @param flags Optional. + */ + installModule(name: string, flags?: number): Promise<void>; + /** + * Remove an installed PKCS#11 module from firefox + */ + uninstallModule(name: string): Promise<void>; + /** + * Enumerate a module's slots, each with their name and whether a token is present + */ + getModuleSlots(name: string): Promise<undefined>; + } + } + /** + * Namespace: browser.privacy + */ + namespace Privacy { + interface Static { + network: Network.Static; + services: Services.Static; + websites: Websites.Static; + } + } + /** + * Namespace: browser.proxy + */ + namespace Proxy { + /** + * An object which describes proxy settings. + */ + interface ProxyConfig { + /** + * The type of proxy to use. + * Optional. + */ + proxyType?: ProxyConfigProxyTypeEnum; + /** + * The address of the http proxy, can include a port. + * Optional. + */ + http?: string; + /** + * Use the http proxy server for all protocols. + * Optional. + */ + httpProxyAll?: boolean; + /** + * The address of the ssl proxy, can include a port. + * Optional. + */ + ssl?: string; + /** + * The address of the socks proxy, can include a port. + * Optional. + */ + socks?: string; + /** + * The version of the socks proxy. + * Optional. + */ + socksVersion?: number; + /** + * A list of hosts which should not be proxied. + * Optional. + */ + passthrough?: string; + /** + * A URL to use to configure the proxy. + * Optional. + */ + autoConfigUrl?: string; + /** + * Do not prompt for authentication if password is saved. + * Optional. + */ + autoLogin?: boolean; + /** + * Proxy DNS when using SOCKS. DNS queries get leaked to the network when set to false. True by default for SOCKS v5. + * False by default for SOCKS v4. + * Optional. + */ + proxyDNS?: boolean; + /** + * If true (the default value), do not use newer TLS protocol features that might have interoperability problems on the + * Internet. This is intended only for use with critical infrastructure like the updates, + * and is only available to privileged addons. + * Optional. + */ + respectBeConservative?: boolean; + } + interface OnRequestDetailsType { + /** + * The ID of the request. Request IDs are unique within a browser session. As a result, + * they could be used to relate different events of the same request. + */ + requestId: string; + url: string; + /** + * Standard HTTP method. + */ + method: string; + /** + * The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in + * which the request happens. If the document of a (sub-)frame is loaded (<code>type</code> is <code>main_frame</code> + * or <code>sub_frame</code>), <code>frameId</code> indicates the ID of this frame, not the ID of the outer frame. + * Frame IDs are unique within a tab. + */ + frameId: number; + /** + * ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists. + */ + parentFrameId: number; + /** + * True for private browsing requests. + * Optional. + */ + incognito?: boolean; + /** + * The cookie store ID of the contextual identity. + * Optional. + */ + cookieStoreId?: string; + /** + * URL of the resource that triggered this request. + * Optional. + */ + originUrl?: string; + /** + * URL of the page into which the requested resource will be loaded. + * Optional. + */ + documentUrl?: string; + /** + * The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab. + */ + tabId: number; + /** + * How the requested resource will be used. + */ + type: Browser.WebRequest.ResourceType; + /** + * The time when this signal is triggered, in milliseconds since the epoch. + */ + timeStamp: number; + /** + * Indicates if this response was fetched from disk cache. + */ + fromCache: boolean; + /** + * The HTTP request headers that are going to be sent out with this request. + * Optional. + */ + requestHeaders?: Browser.WebRequest.HttpHeaders; + /** + * Url classification if the request has been classified. + */ + urlClassification: Browser.WebRequest.UrlClassification; + /** + * Indicates if this request and its content window hierarchy is third party. + */ + thirdParty: boolean; + } + interface OnErrorErrorType { + [s: string]: unknown; + } + /** + * The type of proxy to use. + */ + type ProxyConfigProxyTypeEnum = "none" | "autoDetect" | "system" | "manual" | "autoConfig"; + /** + * Fired when proxy data is needed for a request. + */ + interface OnRequestEvent extends Events.Event<(details: OnRequestDetailsType) => void> { + /** + * Registers an event listener <em>callback</em> to an event. + * + * @param callback Called when an event occurs. The parameters of this function depend on the type of event. + * @param filter A set of filters that restricts the events that will be sent to this listener. + * @param extraInfoSpec Optional. Array of extra information that should be passed to the listener function. + */ + addListener(callback: (details: OnRequestDetailsType) => void, filter: Browser.WebRequest.RequestFilter, extraInfoSpec?: string[]): void; + } + interface Static { + /** + * Fired when proxy data is needed for a request. + */ + onRequest: OnRequestEvent; + /** + * Notifies about errors caused by the invalid use of the proxy API. + */ + onError: Events.Event<(error: OnErrorErrorType) => void>; + /** + * Configures proxy settings. This setting's value is an object of type ProxyConfig. + */ + settings: Browser.Types.Setting; + } + } + /** + * Namespace: browser.runtime + */ + namespace Runtime { + /** + * A filter to match against existing extension context. Matching contexts must match all specified filters. + */ + interface ContextFilter { + /** + * Optional. + */ + contextIds?: string[]; + /** + * Optional. + */ + contextTypes?: ContextType[]; + /** + * Optional. + */ + documentIds?: string[]; + /** + * Optional. + */ + documentOrigins?: string[]; + /** + * Optional. + */ + documentUrls?: string[]; + /** + * Optional. + */ + frameIds?: number[]; + /** + * Optional. + */ + tabIds?: number[]; + /** + * Optional. + */ + windowIds?: number[]; + /** + * Optional. + */ + incognito?: boolean; + } + /** + * The type of extension view. + */ + type ContextType = "BACKGROUND" | "POPUP" | "SIDE_PANEL" | "TAB"; + /** + * A context hosting extension content + */ + interface ExtensionContext { + /** + * An unique identifier associated to this context + */ + contextId: string; + /** + * The type of the context + */ + contextType: ContextType; + /** + * The origin of the document associated with this context, or undefined if it is not hosted in a document + * Optional. + */ + documentOrigin?: string; + /** + * The URL of the document associated with this context, or undefined if it is not hosted in a document + * Optional. + */ + documentUrl?: string; + /** + * Whether the context is associated with an private browsing context. + */ + incognito: boolean; + /** + * The frame ID for this context, or -1 if it is not hosted in a frame. + */ + frameId: number; + /** + * The tab ID for this context, or -1 if it is not hosted in a tab. + */ + tabId: number; + /** + * The window ID for this context, or -1 if it is not hosted in a window. + */ + windowId: number; + } + /** + * An object which allows two way communication with other pages. + */ + interface Port { + name: string; + disconnect(): void; + onDisconnect: Events.Event<(port: Port) => void>; + onMessage: Events.Event<(message: unknown, port: Port) => void>; + /** + * Send a message to the other end. This takes one argument, which is a JSON object representing the message to send. + * It will be delivered to any script listening to the port's onMessage event, or to the native application if this port + * is connected to a native application. + */ + postMessage(message: unknown): void; + /** + * This property will <b>only</b> be present on ports passed to onConnect/onConnectExternal listeners. + * Optional. + */ + sender?: MessageSender; + /** + * If the port was disconnected due to an error, this will be set to an object with a string property message, + * giving you more information about the error. See onDisconnect. + * Optional. + */ + error?: PortErrorType; + } + /** + * An object containing information about the script context that sent a message or request. + */ + interface MessageSender { + /** + * The $(ref:tabs.Tab) which opened the connection, if any. This property will <strong>only</strong> + * be present when the connection was opened from a tab (including content scripts), and <strong>only</strong> + * if the receiver is an extension, not an app. + * Optional. + */ + tab?: Browser.Tabs.Tab; + /** + * The $(topic:frame_ids)[frame] that opened the connection. 0 for top-level frames, positive for child frames. + * This will only be set when <code>tab</code> is set. + * Optional. + */ + frameId?: number; + /** + * The ID of the extension or app that opened the connection, if any. + * Optional. + */ + id?: string; + /** + * The URL of the page or frame that opened the connection. If the sender is in an iframe, + * it will be iframe's URL not the URL of the page which hosts it. + * Optional. + */ + url?: string; + /** + * The worldId of the USER_SCRIPT world that sent the message. Only present on onUserScriptMessage and onUserScriptConnect + * (in port.sender) events. + * Optional. + */ + userScriptWorldId?: string; + } + /** + * The operating system the browser is running on. + */ + type PlatformOs = "mac" | "win" | "android" | "cros" | "linux" | "openbsd"; + /** + * The machine's processor architecture. + */ + type PlatformArch = "aarch64" | "arm" | "ppc64" | "s390x" | "sparc64" | "x86-32" | "x86-64" | "noarch"; + /** + * An object containing information about the current platform. + */ + interface PlatformInfo { + /** + * The operating system the browser is running on. + */ + os: PlatformOs; + /** + * The machine's processor architecture. + */ + arch: PlatformArch; + } + /** + * An object containing information about the current browser. + */ + interface BrowserInfo { + /** + * The name of the browser, for example 'Firefox'. + */ + name: string; + /** + * The name of the browser vendor, for example 'Mozilla'. + */ + vendor: string; + /** + * The browser's version, for example '42.0.0' or '0.8.1pre'. + */ + version: string; + /** + * The browser's build ID/date, for example '20160101'. + */ + buildID: string; + } + /** + * Result of the update check. + */ + type RequestUpdateCheckStatus = "throttled" | "no_update" | "update_available"; + /** + * The reason that this event is being dispatched. + */ + type OnInstalledReason = "install" | "update" | "browser_update"; + /** + * The reason that the event is being dispatched. 'app_update' is used when the restart is needed because the application + * is updated to a newer version. 'os_update' is used when the restart is needed because the browser/OS is updated to a + * newer version. 'periodic' is used when the system runs for more than the permitted uptime set in the enterprise policy. + */ + type OnRestartRequiredReason = "app_update" | "os_update" | "periodic"; + /** + * The performance warning event category, e.g. 'content_script'. + */ + type OnPerformanceWarningCategory = "content_script"; + /** + * The performance warning event severity. Will be 'high' for serious and user-visible issues. + */ + type OnPerformanceWarningSeverity = "low" | "medium" | "high"; + /** + * The third parameter is a function to call (at most once) when you have a response. + * The argument should be any JSON-ifiable object. If you have more than one <code>onMessage</code> + * listener in the same document, then only one may send a response. <code>sendResponse</code> + * becomes invalid when the event listener returns, unless you return true from the event listener to indicate you wish to + * send a response asynchronously (this will keep the message channel open to the other end until <code>sendResponse</code> + * is called). + */ + type OnMessageListenerCallback = (message: unknown, sender: MessageSender, sendResponse: (response: unknown) => void) => true; + /** + * The return value should be a promise of any JSON-ifiable object. If you have more than one <code>onMessage</code> + * listener in the same document, then only one may send a response. + */ + type OnMessageListenerAsync = (message: unknown, sender: MessageSender) => Promise<unknown>; + type OnMessageListenerNoResponse = (message: unknown, sender: MessageSender) => void; + type OnMessageListener = OnMessageListenerCallback | OnMessageListenerAsync | OnMessageListenerNoResponse; + /** + * If an update is available, this contains more information about the available update. + */ + interface RequestUpdateCheckCallbackDetailsType { + /** + * The version of the available update. + */ + version: string; + } + interface ConnectConnectInfoType { + /** + * Will be passed into onConnect for processes that are listening for the connection event. + * Optional. + */ + name?: string; + /** + * Whether the TLS channel ID will be passed into onConnectExternal for processes that are listening for the connection + * event. + * Optional. + */ + includeTlsChannelId?: boolean; + } + interface SendMessageOptionsType { + [s: string]: unknown; + } + interface OnInstalledDetailsType { + /** + * The reason that this event is being dispatched. + */ + reason: OnInstalledReason; + /** + * Indicates the previous version of the extension, which has just been updated. This is present only if 'reason' is + * 'update'. + * Optional. + */ + previousVersion?: string; + /** + * Indicates whether the addon is installed as a temporary extension. + */ + temporary: boolean; + } + /** + * The manifest details of the available update. + */ + interface OnUpdateAvailableDetailsType { + /** + * The version number of the available update. + */ + version: string; + } + interface OnPerformanceWarningDetailsType { + /** + * The performance warning event category, e.g. 'content_script'. + */ + category: OnPerformanceWarningCategory; + /** + * The performance warning event severity, e.g. 'high'. + */ + severity: OnPerformanceWarningSeverity; + /** + * The $(ref:tabs.Tab) that the performance warning relates to, if any. + * Optional. + */ + tabId?: number; + /** + * An explanation of what the warning means, and hopefully how to address it. + */ + description: string; + } + /** + * This will be defined during an API method callback if there was an error + */ + interface PropertyLastErrorType { + /** + * Details about the error which occurred. + * Optional. + */ + message?: string; + } + /** + * If the port was disconnected due to an error, this will be set to an object with a string property message, + * giving you more information about the error. See onDisconnect. + */ + interface PortErrorType { + message: string; + } + interface Static { + /** + * Retrieves the JavaScript 'window' object for the background page running inside the current extension/app. + * If the background page is an event page, the system will ensure it is loaded before calling the callback. + * If there is no background page, an error is set. + */ + getBackgroundPage(): Promise<Window>; + /** + * Fetches information about active contexts associated with this extension + * + * @param filter A filter to find matching context. + */ + getContexts(filter: ContextFilter): Promise<ExtensionContext[]>; + /** + * <p>Open your Extension's options page, if possible.</p><p>The precise behavior may depend on your manifest's <code> + * $(topic:optionsV2)[options_ui]</code> or <code>$(topic:options)[options_page]</code> key, + * or what the browser happens to support at the time.</p><p>If your Extension does not declare an options page, + * or the browser failed to create one for some other reason, the callback will set $(ref:lastError).</p> + */ + openOptionsPage(): Promise<void>; + /** + * Returns details about the app or extension from the manifest. The object returned is a serialization of the full + * $(topic:manifest)[manifest file]. + * + * @returns The manifest details. + */ + getManifest(): Promise<Manifest.WebExtensionManifest>; + /** + * Converts a relative path within an app/extension install directory to a fully-qualified URL. + * + * @param path A path to a resource within an app/extension expressed relative to its install directory. + * @returns The fully-qualified URL to the resource. + */ + getURL(path: string): Promise<string>; + /** + * Get the frameId of any window global or frame element. + * + * @param target A WindowProxy or a Browsing Context container element (IFrame, Frame, Embed, Object) for the target frame. + * @returns The frameId of the target frame, or -1 if it doesn't exist. + */ + getFrameId(target: unknown): number; + /** + * Sets the URL to be visited upon uninstallation. This may be used to clean up server-side data, do analytics, + * and implement surveys. Maximum 1023 characters. + * + * @param url Optional. URL to be opened after the extension is uninstalled. This URL must have an http: or https: scheme. + * Set an empty string to not open a new tab upon uninstallation. + * @returns Called when the uninstall URL is set. If the given URL is invalid, $(ref:runtime.lastError) will be set. + */ + setUninstallURL(url?: string): Promise<void>; + /** + * Reloads the app or extension. + */ + reload(): void; + /** + * Requests an update check for this app/extension. + */ + requestUpdateCheck(): Promise<[ + RequestUpdateCheckStatus, + RequestUpdateCheckCallbackDetailsType + ]>; + /** + * Attempts to connect to connect listeners within an extension/app (such as the background page), or other extensions/apps. + * This is useful for content scripts connecting to their extension processes, inter-app/extension communication, + * and $(topic:manifest/externally_connectable)[web messaging]. Note that this does not connect to any listeners in a + * content script. Extensions may connect to content scripts embedded in tabs via $(ref:tabs.connect). + * + * @param extensionId Optional. The ID of the extension or app to connect to. If omitted, + * a connection will be attempted with your own extension. Required if sending messages from a web page for + * $(topic:manifest/externally_connectable)[web messaging]. + * @param connectInfo Optional. + * @returns Port through which messages can be sent and received. The port's $(ref:runtime.Port onDisconnect) + * event is fired if the extension/app does not exist. + */ + connect(extensionId?: string, connectInfo?: ConnectConnectInfoType): Port; + /** + * Attempts to connect to connect listeners within an extension/app (such as the background page), or other extensions/apps. + * This is useful for content scripts connecting to their extension processes, inter-app/extension communication, + * and $(topic:manifest/externally_connectable)[web messaging]. Note that this does not connect to any listeners in a + * content script. Extensions may connect to content scripts embedded in tabs via $(ref:tabs.connect). + * + * @param connectInfo Optional. + * @returns Port through which messages can be sent and received. The port's $(ref:runtime.Port onDisconnect) + * event is fired if the extension/app does not exist. + */ + connect(connectInfo?: ConnectConnectInfoType): Port; + /** + * Connects to a native application in the host machine. + * + * @param application The name of the registered application to connect to. + * @returns Port through which messages can be sent and received with the application + */ + connectNative(application: string): Port; + /** + * Sends a single message to event listeners within your extension/app or a different extension/app. + * Similar to $(ref:runtime.connect) but only sends a single message, with an optional response. + * If sending to your extension, the $(ref:runtime.onMessage) event will be fired in each page, or $(ref:runtime. + * onMessageExternal), if a different extension. Note that extensions cannot send messages to content scripts using this + * method. To send messages to content scripts, use $(ref:tabs.sendMessage). + * + * @param extensionId Optional. The ID of the extension/app to send the message to. If omitted, + * the message will be sent to your own extension/app. Required if sending messages from a web page for + * $(topic:manifest/externally_connectable)[web messaging]. + * @param options Optional. + */ + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + sendMessage<TMessage = unknown, TResponse = unknown>(extensionId: string | undefined, message: TMessage, options?: SendMessageOptionsType): Promise<TResponse>; + /** + * Sends a single message to event listeners within your extension/app or a different extension/app. + * Similar to $(ref:runtime.connect) but only sends a single message, with an optional response. + * If sending to your extension, the $(ref:runtime.onMessage) event will be fired in each page, or $(ref:runtime. + * onMessageExternal), if a different extension. Note that extensions cannot send messages to content scripts using this + * method. To send messages to content scripts, use $(ref:tabs.sendMessage). + * + * @param options Optional. + */ + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + sendMessage<TMessage = unknown, TResponse = unknown>(message: TMessage, options?: SendMessageOptionsType): Promise<TResponse>; + /** + * Send a single message to a native application. + * + * @param application The name of the native messaging host. + * @param message The message that will be passed to the native messaging host. + */ + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + sendNativeMessage<TMessage = unknown, TResponse = unknown>(application: string, message: TMessage): Promise<TResponse>; + /** + * Returns information about the current browser. + * + * @returns Called with results + */ + getBrowserInfo(): Promise<BrowserInfo>; + /** + * Returns information about the current platform. + * + * @returns Called with results + */ + getPlatformInfo(): Promise<PlatformInfo>; + /** + * Fired when a profile that has this extension installed first starts up. This event is not fired for incognito profiles. + */ + onStartup: Events.Event<() => void>; + /** + * Fired when the extension is first installed, when the extension is updated to a new version, + * and when the browser is updated to a new version. + */ + onInstalled: Events.Event<(details: OnInstalledDetailsType) => void>; + /** + * Sent to the event page just before it is unloaded. This gives the extension opportunity to do some clean up. + * Note that since the page is unloading, any asynchronous operations started while handling this event are not guaranteed + * to complete. If more activity for the event page occurs before it gets unloaded the onSuspendCanceled event will be sent + * and the page won't be unloaded. + */ + onSuspend: Events.Event<() => void>; + /** + * Sent after onSuspend to indicate that the app won't be unloaded after all. + */ + onSuspendCanceled: Events.Event<() => void>; + /** + * Fired when an update is available, but isn't installed immediately because the app is currently running. + * If you do nothing, the update will be installed the next time the background page gets unloaded, + * if you want it to be installed sooner you can explicitly call $(ref:runtime.reload). + * If your extension is using a persistent background page, the background page of course never gets unloaded, + * so unless you call $(ref:runtime.reload) manually in response to this event the update will not get installed until the + * next time the browser itself restarts. If no handlers are listening for this event, + * and your extension has a persistent background page, it behaves as if $(ref:runtime.reload) + * is called in response to this event. + * + * @param details The manifest details of the available update. + */ + onUpdateAvailable: Events.Event<(details: OnUpdateAvailableDetailsType) => void>; + /** + * Fired when a connection is made from either an extension process or a content script. + */ + onConnect: Events.Event<(port: Port) => void>; + /** + * Fired when a connection is made from a USER_SCRIPT world registered through the userScripts API. + */ + onUserScriptConnect: Events.Event<(port: Port) => void>; + /** + * Fired when a connection is made from another extension. + */ + onConnectExternal: Events.Event<(port: Port) => void>; + /** + * Fired when a message is sent from either an extension process or a content script. + */ + onMessage: Events.Event<OnMessageListener>; + /** + * Fired when a message is sent from another extension/app. Cannot be used in a content script. + */ + onMessageExternal: Events.Event<OnMessageListener>; + /** + * Fired when a message is sent from a USER_SCRIPT world registered through the userScripts API. + */ + onUserScriptMessage: Events.Event<OnMessageListener>; + /** + * Fired when a runtime performance issue is detected with the extension. Observe this event to be proactively notified of + * runtime performance problems with the extension. + */ + onPerformanceWarning: Events.Event<(details: OnPerformanceWarningDetailsType) => void>; + /** + * This will be defined during an API method callback if there was an error + * Optional. + */ + lastError?: PropertyLastErrorType; + /** + * The ID of the extension/app. + */ + id: string; + } + } + /** + * Namespace: browser.scripting + */ + namespace Scripting { + /** + * Details of a script injection + */ + interface ScriptInjection { + /** + * The arguments to curry into a provided function. This is only valid if the <code>func</code> parameter is specified. + * These arguments must be JSON-serializable. + * Optional. + */ + args?: unknown[]; + /** + * The path of the JS files to inject, relative to the extension's root directory. Exactly one of <code>files</code> + * and <code>func</code> must be specified. + * Optional. + */ + files?: string[]; + /** + * A JavaScript function to inject. This function will be serialized, and then deserialized for injection. + * This means that any bound parameters and execution context will be lost. Exactly one of <code>files</code> and <code> + * func</code> must be specified. + * + * @param ...args The arguments + * @returns The return value + */ + func?(...args: unknown[]): unknown; + /** + * Details specifying the target into which to inject the script. + */ + target: InjectionTarget; + /** + * Optional. + */ + world?: ExecutionWorld; + /** + * Whether the injection should be triggered in the target as soon as possible (but not necessarily prior to page load). + * Optional. + */ + injectImmediately?: boolean; + } + /** + * Result of a script injection. + */ + interface InjectionResult { + /** + * The frame ID associated with the injection. + */ + frameId: number; + /** + * The result of the script execution. + * Optional. + */ + result?: unknown; + /** + * The error property is set when the script execution failed. The value is typically an (Error) + * object with a message property, but could be any value (including primitives and undefined) + * if the script threw or rejected with such a value. + * Optional. + */ + error?: unknown; + /** + * Whether the script should inject into all frames within the tab. Defaults to false. + * This must not be true if frameIds is specified. + * Optional. + */ + allFrames?: boolean; + } + /** + * Details of the script to insert. + */ + interface InjectionTarget { + /** + * The IDs of specific frames to inject into. + * Optional. + */ + frameIds?: number[]; + /** + * Whether the script should inject into all frames within the tab. Defaults to false. + * This must not be true if frameIds is specified. + * Optional. + */ + allFrames?: boolean; + /** + * The ID of the tab into which to inject. + */ + tabId: number; + } + interface CSSInjection { + /** + * A string containing the CSS to inject. Exactly one of <code>files</code> and <code>css</code> must be specified. + * Optional. + */ + css?: string; + /** + * The path of the CSS files to inject, relative to the extension's root directory. Exactly one of <code>files</code> + * and <code>css</code> must be specified. + * Optional. + */ + files?: string[]; + /** + * The style origin for the injection. Defaults to <code>'AUTHOR'</code>. + * Optional. + */ + origin?: CSSInjectionOriginEnum; + /** + * Details specifying the target into which to inject the CSS. + */ + target: InjectionTarget; + } + interface ContentScriptFilter { + /** + * The IDs of specific scripts to retrieve with <code>getRegisteredContentScripts()</code> or to unregister with <code> + * unregisterContentScripts()</code>. + * Optional. + */ + ids?: string[]; + } + /** + * The JavaScript world for a script to execute within. <code>ISOLATED</code> is the default execution environment of + * content scripts, <code>MAIN</code> is the web page's execution environment. + */ + type ExecutionWorld = "ISOLATED" | "MAIN"; + interface RegisteredContentScript { + /** + * If specified true, it will inject into all frames, even if the frame is not the top-most frame in the tab. + * Each frame is checked independently for URL requirements; it will not inject into child frames if the URL requirements + * are not met. Defaults to false, meaning that only the top frame is matched. + * Optional. + */ + allFrames?: boolean; + /** + * Excludes pages that this content script would otherwise be injected into. + * Optional. + */ + excludeMatches?: string[]; + /** + * The id of the content script, specified in the API call. + */ + id: string; + /** + * The list of JavaScript files to be injected into matching pages. These are injected in the order they appear in this + * array. + * Optional. + */ + js?: Browser.Manifest.ExtensionURL[]; + /** + * Specifies which pages this content script will be injected into. Must be specified for <code>registerContentScripts() + * </code>. + * Optional. + */ + matches?: string[]; + /** + * If matchOriginAsFallback is true, then the code is also injected in about:, data:, + * blob: when their origin matches the pattern in 'matches', even if the actual document origin is opaque (due to the use + * of CSP sandbox or iframe sandbox). Match patterns in 'matches' must specify a wildcard path glob. By default it is <code> + * false</code>. + * Optional. + */ + matchOriginAsFallback?: boolean; + /** + * Specifies when JavaScript files are injected into the web page. The preferred and default value is <code> + * document_idle</code>. + * Optional. + */ + runAt?: Browser.ExtensionTypes.RunAt; + /** + * The JavaScript world for a script to execute within. Defaults to "ISOLATED". + * Optional. + */ + world?: ExecutionWorld; + /** + * Specifies if this content script will persist into future sessions. This is currently NOT supported. + * Optional. + */ + persistAcrossSessions?: boolean; + /** + * The list of CSS files to be injected into matching pages. These are injected in the order they appear in this array. + * Optional. + */ + css?: Browser.Manifest.ExtensionURL[]; + } + /** + * The origin for a style change. See style origins for more info. + * + * "AUTHOR": The author origin is the style origin which contains all of the styles which are part of the document, + * whether embedded within the HTML or loaded from an external stylesheet file. + * "USER": The user origin is the style origin containing any CSS that the user of the web browser has added. + * These may be from adding styles using a developer tool or from a browser extension that automatically applies custom + * styles to content, such as Stylus or Stylish. + */ + type StyleOrigin = "AUTHOR" | "USER"; + /** + * Details of the css to insert. + */ + interface CSSInjection { + /** + * A string containing the CSS to inject. Exactly one of files and css must be specified. + * Optional. + */ + css?: string; + /** + * The path of the CSS files to inject, relative to the extension's root directory. NOTE: Currently a maximum of one file + * is supported. Exactly one of files and css must be specified. + * Optional. + */ + files?: string[]; + /** + * The style origin for the injection. Defaults to 'AUTHOR'. + * Optional. + */ + origin?: StyleOrigin; + /** + * Details specifying the target into which to insert the CSS. + */ + target: InjectionTarget; + } + interface UpdateContentScriptsScriptsItemType extends RegisteredContentScript { + /** + * Specifies if this content script will persist into future sessions. + * Optional. + */ + persistAcrossSessions?: boolean; + } + /** + * The style origin for the injection. Defaults to <code>'AUTHOR'</code>. + */ + type CSSInjectionOriginEnum = "USER" | "AUTHOR"; + interface Static { + /** + * Injects a script into a target context. The script will be run at <code>document_idle</code>. + * + * @param injection The details of the script which to inject. + * @returns Invoked upon completion of the injection. The resulting array contains the result of execution for each frame + * where the injection succeeded. + */ + executeScript(injection: ScriptInjection): Promise<InjectionResult[]>; + /** + * Inserts a CSS stylesheet into a target context. If multiple frames are specified, unsuccessful injections are ignored. + * + * @param injection The details of the styles to insert. + * @returns Invoked upon completion of the injection. + */ + insertCSS(injection: CSSInjection): Promise<void>; + /** + * Removes a CSS stylesheet that was previously inserted by this extension from a target context. + * + * @param injection The details of the styles to remove. Note that the <code>css</code>, <code>files</code>, and <code> + * origin</code> properties must exactly match the stylesheet inserted through <code>insertCSS</code>. + * Attempting to remove a non-existent stylesheet is a no-op. + * @returns Invoked upon completion of the injection. + */ + removeCSS(injection: CSSInjection): Promise<void>; + /** + * Registers one or more content scripts for this extension. + * + * @param scripts Contains a list of scripts to be registered. If there are errors during script parsing/file validation, + * or if the IDs specified already exist, then no scripts are registered. + * @returns Invoked upon completion of the registration. + */ + registerContentScripts(scripts: RegisteredContentScript[]): Promise<void>; + /** + * Returns all dynamically registered content scripts for this extension that match the given filter. + * + * @param filter Optional. An object to filter the extension's dynamically registered scripts. + * @returns The resulting array contains the registered content scripts. + */ + getRegisteredContentScripts(filter?: ContentScriptFilter): Promise<RegisteredContentScript[]>; + /** + * Unregisters one or more content scripts for this extension. + * + * @param filter Optional. If specified, only unregisters dynamic content scripts which match the filter. Otherwise, + * all of the extension's dynamic content scripts are unregistered. + * @returns Invoked upon completion of the unregistration. + */ + unregisterContentScripts(filter?: ContentScriptFilter): Promise<void>; + /** + * Updates one or more content scripts for this extension. + * + * @param scripts Contains a list of scripts to be updated. If there are errors during script parsing/file validation, + * or if the IDs specified do not already exist, then no scripts are updated. + * @returns Invoked when scripts have been updated. + */ + updateContentScripts(scripts: UpdateContentScriptsScriptsItemType[]): Promise<void>; + } + } + /** + * Namespace: browser.search + */ + namespace Search { + /** + * An object encapsulating a search engine + */ + interface SearchEngine { + name: string; + isDefault: boolean; + /** + * Optional. + */ + alias?: string; + /** + * Optional. + */ + favIconUrl?: string; + } + /** + * Location where search results should be displayed. + */ + type Disposition = "CURRENT_TAB" | "NEW_TAB" | "NEW_WINDOW"; + interface SearchSearchPropertiesType { + /** + * Terms to search for. + */ + query: string; + /** + * Search engine to use. Uses the default if not specified. + * Optional. + */ + engine?: string; + /** + * Location where search results should be displayed. NEW_TAB is the default. + * Optional. + */ + disposition?: Disposition; + /** + * The ID of the tab for the search results. If not specified, a new tab is created, unless disposition is set. + * tabId cannot be used with disposition. + * Optional. + */ + tabId?: number; + } + interface QueryQueryInfoType { + /** + * String to query with the default search provider. + */ + text: string; + /** + * Location where search results should be displayed. CURRENT_TAB is the default. + * Optional. + */ + disposition?: Disposition; + /** + * Location where search results should be displayed. tabId cannot be used with disposition. + * Optional. + */ + tabId?: number; + } + interface Static { + /** + * Gets a list of search engines. + * + * @returns A Promise that will be fulfilled with an array of search engine objects. + */ + get(): Promise<SearchEngine[]>; + /** + * Perform a search. + */ + search(searchProperties: SearchSearchPropertiesType): Promise<void>; + /** + * Use the chrome.search API to search via the default provider. + */ + query(queryInfo: QueryQueryInfoType): Promise<void>; + } + } + /** + * Namespace: browser.sessions + */ + namespace Sessions { + interface Filter { + /** + * The maximum number of entries to be fetched in the requested list. Omit this parameter to fetch the maximum number of + * entries ($(ref:sessions.MAX_SESSION_RESULTS)). + * Optional. + */ + maxResults?: number; + } + interface Session { + /** + * The time when the window or tab was closed or modified, represented in milliseconds since the epoch. + */ + lastModified: number; + /** + * The $(ref:tabs.Tab), if this entry describes a tab. Either this or $(ref:sessions.Session.window) will be set. + * Optional. + */ + tab?: Browser.Tabs.Tab; + /** + * The $(ref:windows.Window), if this entry describes a window. Either this or $(ref:sessions.Session.tab) will be set. + * Optional. + */ + window?: Browser.Windows.Window; + } + interface Device { + info: string; + /** + * The name of the foreign device. + */ + deviceName: string; + /** + * A list of open window sessions for the foreign device, sorted from most recently to least recently modified session. + */ + sessions: Session[]; + } + interface Static { + /** + * Forget a recently closed tab. + * + * @param windowId The windowId of the window to which the recently closed tab to be forgotten belongs. + * @param sessionId The sessionId (closedId) of the recently closed tab to be forgotten. + */ + forgetClosedTab(windowId: number, sessionId: string): Promise<void>; + /** + * Forget a recently closed window. + * + * @param sessionId The sessionId (closedId) of the recently closed window to be forgotten. + */ + forgetClosedWindow(sessionId: string): Promise<void>; + /** + * Gets the list of recently closed tabs and/or windows. + * + * @param filter Optional. + */ + getRecentlyClosed(filter?: Filter): Promise<Session[]>; + /** + * Reopens a $(ref:windows.Window) or $(ref:tabs.Tab), with an optional callback to run when the entry has been restored. + * + * @param sessionId Optional. The $(ref:windows.Window.sessionId), or $(ref:tabs.Tab.sessionId) to restore. + * If this parameter is not specified, the most recently closed session is restored. + */ + restore(sessionId?: string): Promise<Session>; + /** + * Set a key/value pair on a given tab. + * + * @param tabId The id of the tab that the key/value pair is being set on. + * @param key The key which corresponds to the value being set. + * @param value The value being set. + */ + setTabValue(tabId: number, key: string, value: unknown): Promise<void>; + /** + * Retrieve a value that was set for a given key on a given tab. + * + * @param tabId The id of the tab whose value is being retrieved from. + * @param key The key which corresponds to the value. + */ + getTabValue(tabId: number, key: string): Promise<unknown>; + /** + * Remove a key/value pair that was set on a given tab. + * + * @param tabId The id of the tab whose key/value pair is being removed. + * @param key The key which corresponds to the value. + */ + removeTabValue(tabId: number, key: string): Promise<void>; + /** + * Set a key/value pair on a given window. + * + * @param windowId The id of the window that the key/value pair is being set on. + * @param key The key which corresponds to the value being set. + * @param value The value being set. + */ + setWindowValue(windowId: number, key: string, value: unknown): Promise<void>; + /** + * Retrieve a value that was set for a given key on a given window. + * + * @param windowId The id of the window whose value is being retrieved from. + * @param key The key which corresponds to the value. + */ + getWindowValue(windowId: number, key: string): Promise<unknown>; + /** + * Remove a key/value pair that was set on a given window. + * + * @param windowId The id of the window whose key/value pair is being removed. + * @param key The key which corresponds to the value. + */ + removeWindowValue(windowId: number, key: string): Promise<void>; + /** + * Fired when recently closed tabs and/or windows are changed. This event does not monitor synced sessions changes. + */ + onChanged: Events.Event<() => void>; + /** + * The maximum number of $(ref:sessions.Session) that will be included in a requested list. + */ + MAX_SESSION_RESULTS: 25; + } + } + /** + * Namespace: browser.sidebarAction + */ + namespace SidebarAction { + /** + * Pixel data for an image. Must be an ImageData object (for example, from a <code>canvas</code> element). + */ + interface ImageDataType extends ImageData { + [s: string]: unknown; + } + interface SetTitleDetailsType { + /** + * The string the sidebar action should display when moused over. + */ + title: string | null; + /** + * Sets the sidebar title for the tab specified by tabId. Automatically resets when the tab is closed. + * Optional. + */ + tabId?: number; + /** + * Sets the sidebar title for the window specified by windowId. + * Optional. + */ + windowId?: number; + } + interface GetTitleDetailsType { + /** + * Specify the tab to get the title from. If no tab nor window is specified, the global title is returned. + * Optional. + */ + tabId?: number; + /** + * Specify the window to get the title from. If no tab nor window is specified, the global title is returned. + * Optional. + */ + windowId?: number; + } + interface SetIconDetailsType { + /** + * Either an ImageData object or a dictionary {size -> ImageData} representing icon to be set. + * If the icon is specified as a dictionary, the actual image to be used is chosen depending on screen's pixel density. + * If the number of image pixels that fit into one screen space unit equals <code>scale</code>, then image with size <code> + * scale</code> * 19 will be selected. Initially only scales 1 and 2 will be supported. + * At least one image must be specified. Note that 'details.imageData = foo' is equivalent to 'details. + * imageData = {'19': foo}' + * Optional. + */ + imageData?: ImageDataType | Record<string, ImageDataType>; + /** + * Either a relative image path or a dictionary {size -> relative image path} pointing to icon to be set. + * If the icon is specified as a dictionary, the actual image to be used is chosen depending on screen's pixel density. + * If the number of image pixels that fit into one screen space unit equals <code>scale</code>, then image with size <code> + * scale</code> * 19 will be selected. Initially only scales 1 and 2 will be supported. + * At least one image must be specified. Note that 'details.path = foo' is equivalent to 'details.imageData = {'19': foo}' + * Optional. + */ + path?: string | SetIconDetailsTypePathC2Type; + /** + * Sets the sidebar icon for the tab specified by tabId. Automatically resets when the tab is closed. + * Optional. + */ + tabId?: number; + /** + * Sets the sidebar icon for the window specified by windowId. + * Optional. + */ + windowId?: number; + } + interface SetPanelDetailsType { + /** + * Sets the sidebar url for the tab specified by tabId. Automatically resets when the tab is closed. + * Optional. + */ + tabId?: number; + /** + * Sets the sidebar url for the window specified by windowId. + * Optional. + */ + windowId?: number; + /** + * The url to the html file to show in a sidebar. If set to the empty string (''), no sidebar is shown. + */ + panel: string | null; + } + interface GetPanelDetailsType { + /** + * Specify the tab to get the panel from. If no tab nor window is specified, the global panel is returned. + * Optional. + */ + tabId?: number; + /** + * Specify the window to get the panel from. If no tab nor window is specified, the global panel is returned. + * Optional. + */ + windowId?: number; + } + interface IsOpenDetailsType { + /** + * Specify the window to get the openness from. + * Optional. + */ + windowId?: number; + } + interface SetIconDetailsTypePathC2Type { + [s: string]: unknown; + } + interface Static { + /** + * Sets the title of the sidebar action. This shows up in the tooltip. + */ + setTitle(details: SetTitleDetailsType): Promise<void>; + /** + * Gets the title of the sidebar action. + */ + getTitle(details: GetTitleDetailsType): Promise<string>; + /** + * Sets the icon for the sidebar action. The icon can be specified either as the path to an image file or as the pixel data + * from a canvas element, or as dictionary of either one of those. Either the <strong>path</strong> or the <strong> + * imageData</strong> property must be specified. + */ + setIcon(details: SetIconDetailsType): Promise<void>; + /** + * Sets the url to the html document to be opened in the sidebar when the user clicks on the sidebar action's icon. + */ + setPanel(details: SetPanelDetailsType): Promise<void>; + /** + * Gets the url to the html document set as the panel for this sidebar action. + */ + getPanel(details: GetPanelDetailsType): Promise<string>; + /** + * Opens the extension sidebar in the active window. + */ + open(): Promise<void>; + /** + * Closes the extension sidebar in the active window if the sidebar belongs to the extension. + */ + close(): Promise<void>; + /** + * Toggles the extension sidebar in the active window. + */ + toggle(): Promise<void>; + /** + * Checks whether the sidebar action is open. + */ + isOpen(details: IsOpenDetailsType): Promise<boolean>; + } + } + /** + * Namespace: browser.storage + */ + namespace Storage { + interface StorageChange { + /** + * The old value of the item, if there was an old value. + * Optional. + */ + oldValue?: unknown; + /** + * The new value of the item, if there is a new value. + * Optional. + */ + newValue?: unknown; + } + interface StorageArea { + /** + * Gets one or more items from storage. + * + * @param keys Optional. A single key to get, list of keys to get, or a dictionary specifying default values (see + * description of the object). An empty list or object will return an empty result object. Pass in <code>null</code> + * to get the entire contents of storage. + * @returns Callback with storage items, or on failure (in which case $(ref:runtime.lastError) will be set). + */ + get(keys?: null | string | string[] | Record<string, unknown>): Promise<Record<string, unknown>>; + /** + * Sets multiple items. + * + * @param items <p>An object which gives each key/value pair to update storage with. Any other key/value pairs in storage + * will not be affected.</p><p>Primitive values such as numbers will serialize as expected. Values with a <code> + * typeof</code> <code>"object"</code> and <code>"function"</code> will typically serialize to <code>{}</code>, + * with the exception of <code>Array</code> (serializes as expected), <code>Date</code>, and <code>Regex</code> + * (serialize using their <code>String</code> representation).</p> + * @returns Callback on success, or on failure (in which case $(ref:runtime.lastError) will be set). + */ + set(items: Record<string, unknown>): Promise<void>; + /** + * Removes one or more items from storage. + * + * @param keys A single key or a list of keys for items to remove. + * @returns Callback on success, or on failure (in which case $(ref:runtime.lastError) will be set). + */ + remove(keys: string | string[]): Promise<void>; + /** + * Removes all items from storage. + * + * @returns Callback on success, or on failure (in which case $(ref:runtime.lastError) will be set). + */ + clear(): Promise<void>; + /** + * Fired when one or more items change. + * + * @param changes Object mapping each key that changed to its corresponding $(ref:storage.StorageChange) for that item. + */ + onChanged: Events.Event<(changes: StorageAreaOnChangedChangesType) => void>; + } + interface StorageAreaWithUsage { + /** + * Gets one or more items from storage. + * + * @param keys Optional. A single key to get, list of keys to get, or a dictionary specifying default values (see + * description of the object). An empty list or object will return an empty result object. Pass in <code>null</code> + * to get the entire contents of storage. + * @returns Callback with storage items, or on failure (in which case $(ref:runtime.lastError) will be set). + */ + get(keys?: null | string | string[] | Record<string, unknown>): Promise<Record<string, unknown>>; + /** + * Gets the amount of space (in bytes) being used by one or more items. + * + * @param keys Optional. A single key or list of keys to get the total usage for. An empty list will return 0. + * Pass in <code>null</code> to get the total usage of all of storage. + * @returns Callback with the amount of space being used by storage, or on failure (in which case $(ref:runtime.lastError) + * will be set). + */ + getBytesInUse(keys?: null | string | string[]): Promise<number>; + /** + * Sets multiple items. + * + * @param items <p>An object which gives each key/value pair to update storage with. Any other key/value pairs in storage + * will not be affected.</p><p>Primitive values such as numbers will serialize as expected. Values with a <code> + * typeof</code> <code>"object"</code> and <code>"function"</code> will typically serialize to <code>{}</code>, + * with the exception of <code>Array</code> (serializes as expected), <code>Date</code>, and <code>Regex</code> + * (serialize using their <code>String</code> representation).</p> + * @returns Callback on success, or on failure (in which case $(ref:runtime.lastError) will be set). + */ + set(items: Record<string, unknown>): Promise<void>; + /** + * Removes one or more items from storage. + * + * @param keys A single key or a list of keys for items to remove. + * @returns Callback on success, or on failure (in which case $(ref:runtime.lastError) will be set). + */ + remove(keys: string | string[]): Promise<void>; + /** + * Removes all items from storage. + * + * @returns Callback on success, or on failure (in which case $(ref:runtime.lastError) will be set). + */ + clear(): Promise<void>; + /** + * Fired when one or more items change. + * + * @param changes Object mapping each key that changed to its corresponding $(ref:storage.StorageChange) for that item. + */ + onChanged: Events.Event<(changes: StorageAreaWithUsageOnChangedChangesType) => void>; + } + /** + * Object mapping each key that changed to its corresponding $(ref:storage.StorageChange) for that item. + */ + interface StorageAreaOnChangedChangesType { + [s: string]: StorageChange; + } + /** + * Object mapping each key that changed to its corresponding $(ref:storage.StorageChange) for that item. + */ + interface StorageAreaWithUsageOnChangedChangesType { + [s: string]: StorageChange; + } + interface Static { + /** + * Fired when one or more items change. + * + * @param changes Object mapping each key that changed to its corresponding $(ref:storage.StorageChange) for that item. + * @param areaName The name of the storage area (<code>"sync"</code>, <code>"local"</code> or <code>"managed"</code>) + * the changes are for. + */ + onChanged: Events.Event<(changes: Record<string, StorageChange>, areaName: string) => void>; + /** + * Items in the <code>sync</code> storage area are synced by the browser. + */ + sync: StorageAreaWithUsage; + /** + * Items in the <code>local</code> storage area are local to each machine. + */ + local: StorageArea; + /** + * Items in the <code>managed</code> storage area are set by administrators or native applications, + * and are read-only for the extension; trying to modify this namespace results in an error. + */ + managed: StorageArea; + /** + * Items in the <code>session</code> storage area are kept in memory, and only until the either browser or extension is + * closed or reloaded. + */ + session: StorageAreaWithUsage; + } + } + /** + * Namespace: browser.tabGroups + */ + namespace TabGroups { + /** + * The group's color, using 'grey' spelling for compatibility with Chromium. + */ + type Color = "blue" | "cyan" | "grey" | "green" | "orange" | "pink" | "purple" | "red" | "yellow"; + /** + * State of a tab group inside of an open window. + */ + interface TabGroup { + /** + * Whether the tab group is collapsed or expanded in the tab strip. + */ + collapsed: boolean; + /** + * User-selected color name for the tab group's label/icons. + */ + color: Color; + /** + * Unique ID of the tab group. + */ + id: number; + /** + * User-defined name of the tab group. + * Optional. + */ + title?: string; + /** + * Window that the tab group is in. + */ + windowId: number; + } + interface MoveMovePropertiesType { + index: number; + /** + * Optional. + */ + windowId?: number; + } + interface QueryQueryInfoType { + /** + * Optional. + */ + collapsed?: boolean; + /** + * Optional. + */ + color?: Color; + /** + * Optional. + */ + title?: string; + /** + * Optional. + */ + windowId?: number; + } + interface UpdateUpdatePropertiesType { + /** + * Optional. + */ + collapsed?: boolean; + /** + * Optional. + */ + color?: Color; + /** + * Optional. + */ + title?: string; + } + interface OnRemovedRemoveInfoType { + /** + * True when the tab group is being closed because its window is being closed. + */ + isWindowClosing: boolean; + } + interface Static { + /** + * Retrieves details about the specified group. + */ + get(groupId: number): Promise<TabGroup>; + /** + * Move a group within, or to another window. + */ + move(groupId: number, moveProperties: MoveMovePropertiesType): Promise<TabGroup>; + /** + * Return all grups, or find groups with specified properties. + */ + query(queryInfo: QueryQueryInfoType): Promise<TabGroup[]>; + /** + * Modifies state of a specified group. + */ + update(groupId: number, updateProperties: UpdateUpdatePropertiesType): Promise<TabGroup>; + /** + * Fired when a tab group is created. + */ + onCreated: Events.Event<(group: TabGroup) => void>; + /** + * Fired when a tab group is moved, within a window or to another window. + */ + onMoved: Events.Event<(group: TabGroup) => void>; + /** + * Fired when a tab group is removed. + */ + onRemoved: Events.Event<(group: TabGroup, removeInfo: OnRemovedRemoveInfoType) => void>; + /** + * Fired when a tab group is updated. + */ + onUpdated: Events.Event<(group: TabGroup) => void>; + /** + * An ID that represents the absence of a group. + */ + TAB_GROUP_ID_NONE: -1; + } + } + /** + * Namespace: browser.tabs + */ + namespace Tabs { + /** + * An event that caused a muted state change. + * + * "user": A user input action has set/overridden the muted state. + * "capture": Tab capture started, forcing a muted state change. + * "extension": An extension, identified by the extensionId field, set the muted state. + */ + type MutedInfoReason = "user" | "capture" | "extension"; + /** + * Tab muted state and the reason for the last state change. + */ + interface MutedInfo { + /** + * Whether the tab is prevented from playing sound (but hasn't necessarily recently produced sound). + * Equivalent to whether the muted audio indicator is showing. + */ + muted: boolean; + /** + * The reason the tab was muted or unmuted. Not set if the tab's mute state has never been changed. + * Optional. + */ + reason?: MutedInfoReason; + /** + * The ID of the extension that changed the muted state. Not set if an extension was not the reason the muted state last + * changed. + * Optional. + */ + extensionId?: string; + } + /** + * Tab sharing state for screen, microphone and camera. + */ + interface SharingState { + /** + * If the tab is sharing the screen the value will be one of "Screen", "Window", or "Application", + * or undefined if not screen sharing. + * Optional. + */ + screen?: string; + /** + * True if the tab is using the camera. + */ + camera: boolean; + /** + * True if the tab is using the microphone. + */ + microphone: boolean; + } + interface Tab { + /** + * The ID of the tab. Tab IDs are unique within a browser session. Under some circumstances a Tab may not be assigned an ID, + * for example when querying foreign tabs using the $(ref:sessions) API, in which case a session ID may be present. + * Tab ID can also be set to $(ref:tabs.TAB_ID_NONE) for apps and devtools windows. + * Optional. + */ + id?: number; + /** + * The zero-based index of the tab within its window. + */ + index: number; + /** + * The ID of the window the tab is contained within. + * Optional. + */ + windowId?: number; + /** + * The ID of the tab that opened this tab, if any. This property is only present if the opener tab still exists. + * Optional. + */ + openerTabId?: number; + /** + * Whether the tab is highlighted. Works as an alias of active + */ + highlighted: boolean; + /** + * Whether the tab is active in its window. (Does not necessarily mean the window is focused.) + */ + active: boolean; + /** + * Whether the tab is pinned. + */ + pinned: boolean; + /** + * The last time the tab was accessed as the number of milliseconds since epoch. + * Optional. + */ + lastAccessed?: number; + /** + * Whether the tab has produced sound over the past couple of seconds (but it might not be heard if also muted). + * Equivalent to whether the speaker audio indicator is showing. + * Optional. + */ + audible?: boolean; + /** + * Whether the tab can be discarded automatically by the browser when resources are low. + * Optional. + */ + autoDiscardable?: boolean; + /** + * Current tab muted state and the reason for the last state change. + * Optional. + */ + mutedInfo?: MutedInfo; + /** + * The URL the tab is displaying. This property is only present if the extension's manifest includes the <code>"tabs"</code> + * permission. + * Optional. + */ + url?: string; + /** + * The title of the tab. This property is only present if the extension's manifest includes the <code>"tabs"</code> + * permission. + * Optional. + */ + title?: string; + /** + * The URL of the tab's favicon. This property is only present if the extension's manifest includes the <code>"tabs"</code> + * permission. It may also be an empty string if the tab is loading. + * Optional. + */ + favIconUrl?: string; + /** + * Either <em>loading</em> or <em>complete</em>. + * Optional. + */ + status?: string; + /** + * True while the tab is not loaded with content. + * Optional. + */ + discarded?: boolean; + /** + * Whether the tab is in an incognito window. + */ + incognito: boolean; + /** + * The width of the tab in pixels. + * Optional. + */ + width?: number; + /** + * The height of the tab in pixels. + * Optional. + */ + height?: number; + /** + * True if the tab is hidden. + * Optional. + */ + hidden?: boolean; + /** + * The session ID used to uniquely identify a Tab obtained from the $(ref:sessions) API. + * Optional. + */ + sessionId?: string; + /** + * The CookieStoreId used for the tab. + * Optional. + */ + cookieStoreId?: string; + /** + * Whether the document in the tab can be rendered in reader mode. + * Optional. + */ + isArticle?: boolean; + /** + * Whether the document in the tab is being rendered in reader mode. + * Optional. + */ + isInReaderMode?: boolean; + /** + * Current tab sharing state for screen, microphone and camera. + * Optional. + */ + sharingState?: SharingState; + /** + * Whether the tab is drawing attention. + * Optional. + */ + attention?: boolean; + /** + * The ID of this tab's successor, if any; $(ref:tabs.TAB_ID_NONE) otherwise. + * Optional. + */ + successorTabId?: number; + /** + * The ID of the group that the tab belongs to. + * Optional. + */ + groupId?: number; + /** + * The URL the tab is navigating to, before it has committed. This property is only present if the extension's manifest + * includes the "tabs" permission and there is a pending navigation. + * Optional. + */ + pendingUrl?: string; + } + /** + * Defines how zoom changes are handled, i.e. which entity is responsible for the actual scaling of the page; defaults to + * <code>automatic</code>. + * + * "automatic": Zoom changes are handled automatically by the browser. + * "manual": Overrides the automatic handling of zoom changes. The <code>onZoomChange</code> event will still be dispatched, + * and it is the responsibility of the extension to listen for this event and manually scale the page. + * This mode does not support <code>per-origin</code> zooming, and will thus ignore the <code>scope</code> + * zoom setting and assume <code>per-tab</code>. + * "disabled": Disables all zooming in the tab. The tab will revert to the default zoom level, + * and all attempted zoom changes will be ignored. + */ + type ZoomSettingsMode = "automatic" | "manual" | "disabled"; + /** + * Defines whether zoom changes will persist for the page's origin, or only take effect in this tab; defaults to <code> + * per-origin</code> when in <code>automatic</code> mode, and <code>per-tab</code> otherwise. + * + * "per-origin": Zoom changes will persist in the zoomed page's origin, i.e. all other tabs navigated to that same origin + * will be zoomed as well. Moreover, <code>per-origin</code> zoom changes are saved with the origin, + * meaning that when navigating to other pages in the same origin, they will all be zoomed to the same zoom factor. + * The <code>per-origin</code> scope is only available in the <code>automatic</code> mode. + * "per-tab": Zoom changes only take effect in this tab, and zoom changes in other tabs will not affect the zooming of this + * tab. Also, <code>per-tab</code> zoom changes are reset on navigation; navigating a tab will always load pages with their + * <code>per-origin</code> zoom factors. + */ + type ZoomSettingsScope = "per-origin" | "per-tab"; + /** + * Defines how zoom changes in a tab are handled and at what scope. + */ + interface ZoomSettings { + /** + * Defines how zoom changes are handled, i.e. which entity is responsible for the actual scaling of the page; defaults to + * <code>automatic</code>. + * Optional. + */ + mode?: ZoomSettingsMode; + /** + * Defines whether zoom changes will persist for the page's origin, or only take effect in this tab; defaults to <code> + * per-origin</code> when in <code>automatic</code> mode, and <code>per-tab</code> otherwise. + * Optional. + */ + scope?: ZoomSettingsScope; + /** + * Used to return the default zoom level for the current tab in calls to tabs.getZoomSettings. + * Optional. + */ + defaultZoomFactor?: number; + } + /** + * Defines the page settings to be used when saving a page as a pdf file. + */ + interface PageSettings { + /** + * The name of the file. May include optional .pdf extension. + * Optional. + */ + toFileName?: string; + /** + * The page size unit: 0 = inches, 1 = millimeters. Default: 0. + * Optional. + */ + paperSizeUnit?: number; + /** + * The paper width in paper size units. Default: 8.5. + * Optional. + */ + paperWidth?: number; + /** + * The paper height in paper size units. Default: 11.0. + * Optional. + */ + paperHeight?: number; + /** + * The page content orientation: 0 = portrait, 1 = landscape. Default: 0. + * Optional. + */ + orientation?: number; + /** + * The page content scaling factor: 1.0 = 100% = normal size. Default: 1.0. + * Optional. + */ + scaling?: number; + /** + * Whether the page content should shrink to fit the page width (overrides scaling). Default: true. + * Optional. + */ + shrinkToFit?: boolean; + /** + * Whether the page background colors should be shown. Default: false. + * Optional. + */ + showBackgroundColors?: boolean; + /** + * Whether the page background images should be shown. Default: false. + * Optional. + */ + showBackgroundImages?: boolean; + /** + * The spacing between the left header/footer and the left edge of the paper (inches). Default: 0. + * Optional. + */ + edgeLeft?: number; + /** + * The spacing between the right header/footer and the right edge of the paper (inches). Default: 0. + * Optional. + */ + edgeRight?: number; + /** + * The spacing between the top of the headers and the top edge of the paper (inches). Default: 0 + * Optional. + */ + edgeTop?: number; + /** + * The spacing between the bottom of the footers and the bottom edge of the paper (inches). Default: 0. + * Optional. + */ + edgeBottom?: number; + /** + * The margin between the page content and the left edge of the paper (inches). Default: 0.5. + * Optional. + */ + marginLeft?: number; + /** + * The margin between the page content and the right edge of the paper (inches). Default: 0.5. + * Optional. + */ + marginRight?: number; + /** + * The margin between the page content and the top edge of the paper (inches). Default: 0.5. + * Optional. + */ + marginTop?: number; + /** + * The margin between the page content and the bottom edge of the paper (inches). Default: 0.5. + * Optional. + */ + marginBottom?: number; + /** + * The text for the page's left header. Default: '&T'. + * Optional. + */ + headerLeft?: string; + /** + * The text for the page's center header. Default: ''. + * Optional. + */ + headerCenter?: string; + /** + * The text for the page's right header. Default: '&U'. + * Optional. + */ + headerRight?: string; + /** + * The text for the page's left footer. Default: '&PT'. + * Optional. + */ + footerLeft?: string; + /** + * The text for the page's center footer. Default: ''. + * Optional. + */ + footerCenter?: string; + /** + * The text for the page's right footer. Default: '&D'. + * Optional. + */ + footerRight?: string; + } + /** + * Whether the tabs have completed loading. + */ + type TabStatus = "loading" | "complete"; + /** + * The type of window. + */ + type WindowType = "normal" | "popup" | "panel" | "app" | "devtools"; + /** + * Event names supported in onUpdated. + */ + type UpdatePropertyName = "attention" | "audible" | "autoDiscardable" | "discarded" | "favIconUrl" | "groupId" | "hidden" | "isArticle" | "mutedInfo" | "pinned" | "sharingState" | "status" | "title" | "url"; + /** + * An object describing filters to apply to tabs.onUpdated events. + */ + interface UpdateFilter { + /** + * A list of URLs or URL patterns. Events that cannot match any of the URLs will be filtered out. + * Filtering with urls requires the <code>"tabs"</code> or <code>"activeTab"</code> permission. + * Optional. + */ + urls?: string[]; + /** + * A list of property names. Events that do not match any of the names will be filtered out. + * Optional. + */ + properties?: UpdatePropertyName[]; + /** + * Optional. + */ + tabId?: number; + /** + * Optional. + */ + windowId?: number; + } + interface ConnectConnectInfoType { + /** + * Will be passed into onConnect for content scripts that are listening for the connection event. + * Optional. + */ + name?: string; + /** + * Open a port to a specific $(topic:frame_ids)[frame] identified by <code>frameId</code> instead of all frames in the tab. + * Optional. + */ + frameId?: number; + } + interface SendMessageOptionsType { + /** + * Send a message to a specific $(topic:frame_ids)[frame] identified by <code>frameId</code> + * instead of all frames in the tab. + * Optional. + */ + frameId?: number; + } + interface CreateCreatePropertiesType { + /** + * The window to create the new tab in. Defaults to the $(topic:current-window)[current window]. + * Optional. + */ + windowId?: number; + /** + * The position the tab should take in the window. The provided value will be clamped to between zero and the number of + * tabs in the window. + * Optional. + */ + index?: number; + /** + * The URL to navigate the tab to initially. Fully-qualified URLs must include a scheme (i.e. 'http://www.google.com', + * not 'www.google.com'). Relative URLs will be relative to the current page within the extension. + * Defaults to the New Tab Page. + * Optional. + */ + url?: string; + /** + * Whether the tab should become the active tab in the window. Does not affect whether the window is focused (see + * $(ref:windows.update)). Defaults to <var>true</var>. + * Optional. + */ + active?: boolean; + /** + * Whether the tab should be pinned. Defaults to <var>false</var> + * Optional. + */ + pinned?: boolean; + /** + * The ID of the tab that opened this tab. If specified, the opener tab must be in the same window as the newly created tab. + * Optional. + */ + openerTabId?: number; + /** + * The CookieStoreId for the tab that opened this tab. + * Optional. + */ + cookieStoreId?: string; + /** + * Whether the document in the tab should be opened in reader mode. + * Optional. + */ + openInReaderMode?: boolean; + /** + * Whether the tab is marked as 'discarded' when created. + * Optional. + */ + discarded?: boolean; + /** + * The title used for display if the tab is created in discarded mode. + * Optional. + */ + title?: string; + /** + * Whether the tab should be muted when created. + * Optional. + */ + muted?: boolean; + } + interface DuplicateDuplicatePropertiesType { + /** + * The position the new tab should take in the window. The provided value will be clamped to between zero and the number of + * tabs in the window. + * Optional. + */ + index?: number; + /** + * Whether the tab should become the active tab in the window. Does not affect whether the window is focused (see + * $(ref:windows.update)). Defaults to <var>true</var>. + * Optional. + */ + active?: boolean; + } + interface QueryQueryInfoType { + /** + * Whether the tabs are active in their windows. + * Optional. + */ + active?: boolean; + /** + * Whether the tabs are drawing attention. + * Optional. + */ + attention?: boolean; + /** + * Whether the tabs are pinned. + * Optional. + */ + pinned?: boolean; + /** + * Whether the tabs are audible. + * Optional. + */ + audible?: boolean; + /** + * Whether the tabs can be discarded automatically by the browser when resources are low. + * Optional. + */ + autoDiscardable?: boolean; + /** + * Whether the tabs are muted. + * Optional. + */ + muted?: boolean; + /** + * Whether the tabs are highlighted. Works as an alias of active. + * Optional. + */ + highlighted?: boolean; + /** + * Whether the tabs are in the $(topic:current-window)[current window]. + * Optional. + */ + currentWindow?: boolean; + /** + * Whether the tabs are in the last focused window. + * Optional. + */ + lastFocusedWindow?: boolean; + /** + * Whether the tabs have completed loading. + * Optional. + */ + status?: TabStatus; + /** + * True while the tabs are not loaded with content. + * Optional. + */ + discarded?: boolean; + /** + * True while the tabs are hidden. + * Optional. + */ + hidden?: boolean; + /** + * Match page titles against a pattern. + * Optional. + */ + title?: string; + /** + * Match tabs against one or more $(topic:match_patterns)[URL patterns]. Note that fragment identifiers are not matched. + * Optional. + */ + url?: string | string[]; + /** + * The ID of the parent window, or $(ref:windows.WINDOW_ID_CURRENT) for the $(topic:current-window)[current window]. + * Optional. + */ + windowId?: number; + /** + * The type of window the tabs are in. + * Optional. + */ + windowType?: WindowType; + /** + * The position of the tabs within their windows. + * Optional. + */ + index?: number; + /** + * The CookieStoreId used for the tab. + * Optional. + */ + cookieStoreId?: string[] | string; + /** + * The ID of the tab that opened this tab. If specified, the opener tab must be in the same window as this tab. + * Optional. + */ + openerTabId?: number; + /** + * The ID of the group that the tabs are in, or $(ref:tabGroups.TAB_GROUP_ID_NONE) (-1) for ungrouped tabs. + * Optional. + */ + groupId?: number; + /** + * True for any screen sharing, or a string to specify type of screen sharing. + * Optional. + */ + screen?: "Screen" | "Window" | "Application" | boolean; + /** + * True if the tab is using the camera. + * Optional. + */ + camera?: boolean; + /** + * True if the tab is using the microphone. + * Optional. + */ + microphone?: boolean; + } + interface HighlightHighlightInfoType { + /** + * The window that contains the tabs. + * Optional. + */ + windowId?: number; + /** + * If true, the $(ref:windows.Window) returned will have a <var>tabs</var> property that contains a list of the $(ref:tabs. + * Tab) objects. The <code>Tab</code> objects only contain the <code>url</code>, <code>title</code> and <code> + * favIconUrl</code> properties if the extension's manifest file includes the <code>"tabs"</code> permission. If false, + * the $(ref:windows.Window) won't have the <var>tabs</var> property. + * Optional. + */ + populate?: boolean; + /** + * One or more tab indices to highlight. + */ + tabs: number[] | number; + } + interface UpdateUpdatePropertiesType { + /** + * A URL to navigate the tab to. + * Optional. + */ + url?: string; + /** + * Whether the tab should be active. Does not affect whether the window is focused (see $(ref:windows.update)). + * Optional. + */ + active?: boolean; + /** + * Whether the tab should be discarded automatically by the browser when resources are low. + * Optional. + */ + autoDiscardable?: boolean; + /** + * Adds or removes the tab from the current selection. + * Optional. + */ + highlighted?: boolean; + /** + * Whether the tab should be pinned. + * Optional. + */ + pinned?: boolean; + /** + * Whether the tab should be muted. + * Optional. + */ + muted?: boolean; + /** + * The ID of the tab that opened this tab. If specified, the opener tab must be in the same window as this tab. + * Optional. + */ + openerTabId?: number; + /** + * Whether the load should replace the current history entry for the tab. + * Optional. + */ + loadReplace?: boolean; + /** + * The ID of this tab's successor. If specified, the successor tab must be in the same window as this tab. + * Optional. + */ + successorTabId?: number; + } + interface MoveMovePropertiesType { + /** + * Defaults to the window the tab is currently in. + * Optional. + */ + windowId?: number; + /** + * The position to move the window to. -1 will place the tab at the end of the window. + */ + index: number; + } + interface ReloadReloadPropertiesType { + /** + * Whether using any local cache. Default is false. + * Optional. + */ + bypassCache?: boolean; + } + interface MoveInSuccessionOptionsType { + /** + * Whether to move the tabs before (false) or after (true) tabId in the succession. Defaults to false. + * Optional. + */ + append?: boolean; + /** + * Whether to link up the current predecessors or successor (depending on options.append) + * of tabId to the other side of the chain after it is prepended or appended. If true, + * one of the following happens: if options.append is false, the first tab in the array is set as the successor of any + * current predecessors of tabId; if options.append is true, the current successor of tabId is set as the successor of the + * last tab in the array. Defaults to false. + * Optional. + */ + insert?: boolean; + } + interface GroupOptionsType { + /** + * The tab ID or list of tab IDs to add to the specified group. + */ + tabIds: number | number[]; + /** + * The ID of the group to add the tabs to. If not specified, a new group will be created. + * Optional. + */ + groupId?: number; + /** + * Configurations for creating a group. Cannot be used if groupId is already specified. + * Optional. + */ + createProperties?: GroupOptionsTypeCreatePropertiesType; + } + /** + * Lists the changes to the state of the tab that was updated. + */ + interface OnUpdatedChangeInfoType { + /** + * The tab's new attention state. + * Optional. + */ + attention?: boolean; + /** + * The tab's new audible state. + * Optional. + */ + audible?: boolean; + /** + * The tab's new autoDiscardable state. + * Optional. + */ + autoDiscardable?: boolean; + /** + * True while the tab is not loaded with content. + * Optional. + */ + discarded?: boolean; + /** + * The tab's new favicon URL. This property is only present if the extension's manifest includes the <code>"tabs"</code> + * permission. + * Optional. + */ + favIconUrl?: string; + /** + * The tab's new hidden state. + * Optional. + */ + hidden?: boolean; + /** + * Whether the document in the tab can be rendered in reader mode. + * Optional. + */ + isArticle?: boolean; + /** + * The tab's new muted state and the reason for the change. + * Optional. + */ + mutedInfo?: MutedInfo; + /** + * The tab's new pinned state. + * Optional. + */ + pinned?: boolean; + /** + * The tab's new sharing state for screen, microphone and camera. + * Optional. + */ + sharingState?: SharingState; + /** + * The status of the tab. Can be either <em>loading</em> or <em>complete</em>. + * Optional. + */ + status?: string; + /** + * The title of the tab if it has changed. This property is only present if the extension's manifest includes the <code> + * "tabs"</code> permission. + * Optional. + */ + title?: string; + /** + * The tab's URL if it has changed. This property is only present if the extension's manifest includes the <code> + * "tabs"</code> permission. + * Optional. + */ + url?: string; + } + interface OnMovedMoveInfoType { + windowId: number; + fromIndex: number; + toIndex: number; + } + interface OnActivatedActiveInfoType { + /** + * The ID of the tab that has become active. + */ + tabId: number; + /** + * The ID of the tab that was previously active, if that tab is still open. + * Optional. + */ + previousTabId?: number; + /** + * The ID of the window the active tab changed inside of. + */ + windowId: number; + } + interface OnHighlightedHighlightInfoType { + /** + * The window whose tabs changed. + */ + windowId: number; + /** + * All highlighted tabs in the window. + */ + tabIds: number[]; + } + interface OnDetachedDetachInfoType { + oldWindowId: number; + oldPosition: number; + } + interface OnAttachedAttachInfoType { + newWindowId: number; + newPosition: number; + } + interface OnRemovedRemoveInfoType { + /** + * The window whose tab is closed. + */ + windowId: number; + /** + * True when the tab is being closed because its window is being closed. + */ + isWindowClosing: boolean; + } + interface OnZoomChangeZoomChangeInfoType { + tabId: number; + oldZoomFactor: number; + newZoomFactor: number; + zoomSettings: ZoomSettings; + } + /** + * Configurations for creating a group. Cannot be used if groupId is already specified. + */ + interface GroupOptionsTypeCreatePropertiesType { + /** + * The window of the new group. Defaults to the current window. + * Optional. + */ + windowId?: number; + } + /** + * Fired when a tab is updated. + */ + interface OnUpdatedEvent extends Events.Event<(tabId: number, changeInfo: OnUpdatedChangeInfoType, tab: Tab) => void> { + /** + * Registers an event listener <em>callback</em> to an event. + * + * @param callback Called when an event occurs. The parameters of this function depend on the type of event. + * @param filter Optional. A set of filters that restricts the events that will be sent to this listener. + */ + addListener(callback: (tabId: number, changeInfo: OnUpdatedChangeInfoType, tab: Tab) => void, filter?: UpdateFilter): void; + } + interface Static { + /** + * Retrieves details about the specified tab. + */ + get(tabId: number): Promise<Tab>; + /** + * Gets the tab that this script call is being made from. May be undefined if called from a non-tab context (for example: a + * background page or popup view). + */ + getCurrent(): Promise<Tab>; + /** + * Connects to the content script(s) in the specified tab. The $(ref:runtime.onConnect) + * event is fired in each content script running in the specified tab for the current extension. For more details, + * see $(topic:messaging)[Content Script Messaging]. + * + * @param connectInfo Optional. + * @returns A port that can be used to communicate with the content scripts running in the specified tab. + * The port's $(ref:runtime.Port) event is fired if the tab closes or does not exist. + */ + connect(tabId: number, connectInfo?: ConnectConnectInfoType): Browser.Runtime.Port; + /** + * Sends a single message to the content script(s) in the specified tab, with an optional callback to run when a response + * is sent back. The $(ref:runtime.onMessage) event is fired in each content script running in the specified tab for the + * current extension. + * + * @param options Optional. + */ + // eslint-disable-next-line @definitelytyped/no-unnecessary-generics + sendMessage<TMessage = unknown, TResponse = unknown>(tabId: number, message: TMessage, options?: SendMessageOptionsType): Promise<TResponse>; + /** + * Creates a new tab. + */ + create(createProperties: CreateCreatePropertiesType): Promise<Tab>; + /** + * Duplicates a tab. + * + * @param tabId The ID of the tab which is to be duplicated. + * @param duplicateProperties Optional. + */ + duplicate(tabId: number, duplicateProperties?: DuplicateDuplicatePropertiesType): Promise<Tab>; + /** + * Gets all tabs that have the specified properties, or all tabs if no properties are specified. + */ + query(queryInfo: QueryQueryInfoType): Promise<Tab[]>; + /** + * Highlights the given tabs. + */ + highlight(highlightInfo: HighlightHighlightInfoType): Promise<Browser.Windows.Window>; + /** + * Modifies the properties of a tab. Properties that are not specified in <var>updateProperties</var> are not modified. + * + * @param tabId Optional. Defaults to the selected tab of the $(topic:current-window)[current window]. + */ + update(tabId: number | undefined, updateProperties: UpdateUpdatePropertiesType): Promise<Tab>; + /** + * Modifies the properties of a tab. Properties that are not specified in <var>updateProperties</var> are not modified. + */ + update(updateProperties: UpdateUpdatePropertiesType): Promise<Tab>; + /** + * Moves one or more tabs to a new position within its window, or to a new window. Note that tabs can only be moved to and + * from normal (window.type === "normal") windows. + * + * @param tabIds The tab or list of tabs to move. + */ + move(tabIds: number | number[], moveProperties: MoveMovePropertiesType): Promise<Tab | Tab[]>; + /** + * Reload a tab. + * + * @param tabId Optional. The ID of the tab to reload; defaults to the selected tab of the current window. + * @param reloadProperties Optional. + */ + reload(tabId?: number, reloadProperties?: ReloadReloadPropertiesType): Promise<void>; + /** + * Warm up a tab + * + * @param tabId The ID of the tab to warm up. + */ + warmup(tabId: number): Promise<void>; + /** + * Closes one or more tabs. + * + * @param tabIds The tab or list of tabs to close. + */ + remove(tabIds: number | number[]): Promise<void>; + /** + * discards one or more tabs. + * + * @param tabIds The tab or list of tabs to discard. + */ + discard(tabIds: number | number[]): Promise<void>; + /** + * Detects the primary language of the content in a tab. + * + * @param tabId Optional. Defaults to the active tab of the $(topic:current-window)[current window]. + */ + detectLanguage(tabId?: number): Promise<string>; + /** + * Toggles reader mode for the document in the tab. + * + * @param tabId Optional. Defaults to the active tab of the $(topic:current-window)[current window]. + */ + toggleReaderMode(tabId?: number): Promise<void>; + /** + * Captures an area of a specified tab. You must have $(topic:declare_permissions)[<all_urls>] + * permission to use this method. + * + * @param tabId Optional. The tab to capture. Defaults to the active tab of the current window. + * @param options Optional. + */ + captureTab(tabId?: number, options?: Browser.ExtensionTypes.ImageDetails): Promise<string>; + /** + * Captures an area of the currently active tab in the specified window. You must have <all_urls> or activeTab + * permission to use this method. + * + * @param windowId Optional. The target window. Defaults to the $(topic:current-window)[current window]. + * @param options Optional. + */ + captureVisibleTab(windowId?: number, options?: Browser.ExtensionTypes.ImageDetails): Promise<string>; + /** + * Injects JavaScript code into a page. For details, see the $(topic:content_scripts)[programmatic injection] + * section of the content scripts doc. + * + * @param tabId Optional. The ID of the tab in which to run the script; defaults to the active tab of the current window. + * @param details Details of the script to run. + * @returns Called after all the JavaScript has been executed. + */ + executeScript(tabId: number | undefined, details: Browser.ExtensionTypes.InjectDetails): Promise<unknown[]>; + /** + * Injects JavaScript code into a page. For details, see the $(topic:content_scripts)[programmatic injection] + * section of the content scripts doc. + * + * @param details Details of the script to run. + * @returns Called after all the JavaScript has been executed. + */ + executeScript(details: Browser.ExtensionTypes.InjectDetails): Promise<unknown[]>; + /** + * Injects CSS into a page. For details, see the $(topic:content_scripts)[programmatic injection] + * section of the content scripts doc. + * + * @param tabId Optional. The ID of the tab in which to insert the CSS; defaults to the active tab of the current window. + * @param details Details of the CSS text to insert. + * @returns Called when all the CSS has been inserted. + */ + insertCSS(tabId: number | undefined, details: Browser.ExtensionTypes.InjectDetails): Promise<void>; + /** + * Injects CSS into a page. For details, see the $(topic:content_scripts)[programmatic injection] + * section of the content scripts doc. + * + * @param details Details of the CSS text to insert. + * @returns Called when all the CSS has been inserted. + */ + insertCSS(details: Browser.ExtensionTypes.InjectDetails): Promise<void>; + /** + * Removes injected CSS from a page. For details, see the $(topic:content_scripts)[programmatic injection] + * section of the content scripts doc. + * + * @param tabId Optional. The ID of the tab from which to remove the injected CSS; defaults to the active tab of the + * current window. + * @param details Details of the CSS text to remove. + * @returns Called when all the CSS has been removed. + */ + removeCSS(tabId: number | undefined, details: Browser.ExtensionTypes.InjectDetails): Promise<void>; + /** + * Removes injected CSS from a page. For details, see the $(topic:content_scripts)[programmatic injection] + * section of the content scripts doc. + * + * @param details Details of the CSS text to remove. + * @returns Called when all the CSS has been removed. + */ + removeCSS(details: Browser.ExtensionTypes.InjectDetails): Promise<void>; + /** + * Zooms a specified tab. + * + * @param tabId Optional. The ID of the tab to zoom; defaults to the active tab of the current window. + * @param zoomFactor The new zoom factor. Use a value of 0 here to set the tab to its current default zoom factor. + * Values greater than zero specify a (possibly non-default) zoom factor for the tab. + * @returns Called after the zoom factor has been changed. + */ + setZoom(tabId: number | undefined, zoomFactor: number): Promise<void>; + /** + * Zooms a specified tab. + * + * @param zoomFactor The new zoom factor. Use a value of 0 here to set the tab to its current default zoom factor. + * Values greater than zero specify a (possibly non-default) zoom factor for the tab. + * @returns Called after the zoom factor has been changed. + */ + setZoom(zoomFactor: number): Promise<void>; + /** + * Gets the current zoom factor of a specified tab. + * + * @param tabId Optional. The ID of the tab to get the current zoom factor from; defaults to the active tab of the current + * window. + * @returns Called with the tab's current zoom factor after it has been fetched. + */ + getZoom(tabId?: number): Promise<number>; + /** + * Sets the zoom settings for a specified tab, which define how zoom changes are handled. + * These settings are reset to defaults upon navigating the tab. + * + * @param tabId Optional. The ID of the tab to change the zoom settings for; defaults to the active tab of the current + * window. + * @param zoomSettings Defines how zoom changes are handled and at what scope. + * @returns Called after the zoom settings have been changed. + */ + setZoomSettings(tabId: number | undefined, zoomSettings: ZoomSettings): Promise<void>; + /** + * Sets the zoom settings for a specified tab, which define how zoom changes are handled. + * These settings are reset to defaults upon navigating the tab. + * + * @param zoomSettings Defines how zoom changes are handled and at what scope. + * @returns Called after the zoom settings have been changed. + */ + setZoomSettings(zoomSettings: ZoomSettings): Promise<void>; + /** + * Gets the current zoom settings of a specified tab. + * + * @param tabId Optional. The ID of the tab to get the current zoom settings from; defaults to the active tab of the + * current window. + * @returns Called with the tab's current zoom settings. + */ + getZoomSettings(tabId?: number): Promise<ZoomSettings>; + /** + * Prints page in active tab. + */ + print(): void; + /** + * Shows print preview for page in active tab. + * + * @returns Called after print preview entered. + */ + printPreview(): Promise<void>; + /** + * Saves page in active tab as a PDF file. + * + * @param pageSettings The page settings used to save the PDF file. + * @returns Called after save as dialog closed. + */ + saveAsPDF(pageSettings: PageSettings): Promise<string>; + /** + * Shows one or more tabs. + * + * @param tabIds The TAB ID or list of TAB IDs to show. + */ + show(tabIds: number | number[]): Promise<void>; + /** + * Hides one or more tabs. The <code>"tabHide"</code> permission is required to hide tabs. Not all tabs are hidable. + * Returns an array of hidden tabs. + * + * @param tabIds The TAB ID or list of TAB IDs to hide. + */ + hide(tabIds: number | number[]): Promise<number[]>; + /** + * Removes an array of tabs from their lines of succession and prepends or appends them in a chain to another tab. + * + * @param tabIds An array of tab IDs to move in the line of succession. For each tab in the array, + * the tab's current predecessors will have their successor set to the tab's current successor, + * and each tab will then be set to be the successor of the previous tab in the array. + * Any tabs not in the same window as the tab indicated by the second argument (or the first tab in the array, + * if no second argument) will be skipped. + * @param tabId Optional. The ID of a tab to set as the successor of the last tab in the array, or $(ref:tabs.TAB_ID_NONE) + * to leave the last tab without a successor. If options.append is true, then this tab is made the predecessor of the + * first tab in the array instead. + * @param options Optional. + */ + moveInSuccession(tabIds: number[], tabId?: number, options?: MoveInSuccessionOptionsType): Promise<void>; + /** + * Navigate to next page in tab's history, if available + * + * @param tabId Optional. The ID of the tab to navigate forward. + */ + goForward(tabId?: number): Promise<void>; + /** + * Navigate to previous page in tab's history, if available. + * + * @param tabId Optional. The ID of the tab to navigate backward. + */ + goBack(tabId?: number): Promise<void>; + /** + * Adds one or more tabs to a specified group, or if no group is specified, adds the given tabs to a newly created group. + */ + group(options: GroupOptionsType): Promise<number>; + /** + * Removes one or more tabs from their respective groups. If any groups become empty, they are deleted. + * + * @param tabIds The tab ID or list of tab IDs to remove from their respective groups. + */ + ungroup(tabIds: number | number[]): Promise<void>; + /** + * Fired when a tab is created. Note that the tab's URL may not be set at the time this event fired, + * but you can listen to onUpdated events to be notified when a URL is set. + * + * @param tab Details of the tab that was created. + */ + onCreated: Events.Event<(tab: Tab) => void>; + /** + * Fired when a tab is updated. + */ + onUpdated: OnUpdatedEvent; + /** + * Fired when a tab is moved within a window. Only one move event is fired, representing the tab the user directly moved. + * Move events are not fired for the other tabs that must move in response. This event is not fired when a tab is moved + * between windows. For that, see $(ref:tabs.onDetached). + */ + onMoved: Events.Event<(tabId: number, moveInfo: OnMovedMoveInfoType) => void>; + /** + * Fires when the active tab in a window changes. Note that the tab's URL may not be set at the time this event fired, + * but you can listen to onUpdated events to be notified when a URL is set. + */ + onActivated: Events.Event<(activeInfo: OnActivatedActiveInfoType) => void>; + /** + * Fired when the highlighted or selected tabs in a window changes. + */ + onHighlighted: Events.Event<(highlightInfo: OnHighlightedHighlightInfoType) => void>; + /** + * Fired when a tab is detached from a window, for example because it is being moved between windows. + */ + onDetached: Events.Event<(tabId: number, detachInfo: OnDetachedDetachInfoType) => void>; + /** + * Fired when a tab is attached to a window, for example because it was moved between windows. + */ + onAttached: Events.Event<(tabId: number, attachInfo: OnAttachedAttachInfoType) => void>; + /** + * Fired when a tab is closed. + */ + onRemoved: Events.Event<(tabId: number, removeInfo: OnRemovedRemoveInfoType) => void>; + /** + * Fired when a tab is replaced with another tab due to prerendering or instant. + */ + onReplaced: Events.Event<(addedTabId: number, removedTabId: number) => void>; + /** + * Fired when a tab is zoomed. + */ + onZoomChange: Events.Event<(ZoomChangeInfo: OnZoomChangeZoomChangeInfoType) => void>; + /** + * An ID which represents the absence of a browser tab. + */ + TAB_ID_NONE: -1; + } + } + /** + * Namespace: browser.theme + */ + namespace Theme { + /** + * Info provided in the onUpdated listener. + */ + interface ThemeUpdateInfo { + /** + * The new theme after update + */ + theme: ThemeUpdateInfoThemeType; + /** + * The id of the window the theme has been applied to + * Optional. + */ + windowId?: number; + } + /** + * The new theme after update + */ + interface ThemeUpdateInfoThemeType { + [s: string]: unknown; + } + interface Static { + /** + * Returns the current theme for the specified window or the last focused window. + * + * @param windowId Optional. The window for which we want the theme. + */ + getCurrent(windowId?: number): Promise<Manifest.ThemeType>; + /** + * Make complete updates to the theme. Resolves when the update has completed. + * + * @param windowId Optional. The id of the window to update. No id updates all windows. + * @param details The properties of the theme to update. + */ + update(windowId: number | undefined, details: Browser.Manifest.ThemeType): Promise<void>; + /** + * Make complete updates to the theme. Resolves when the update has completed. + * + * @param details The properties of the theme to update. + */ + update(details: Browser.Manifest.ThemeType): Promise<void>; + /** + * Removes the updates made to the theme. + * + * @param windowId Optional. The id of the window to reset. No id resets all windows. + */ + reset(windowId?: number): Promise<void>; + /** + * Fired when a new theme has been applied + * + * @param updateInfo Details of the theme update + */ + onUpdated: Events.Event<(updateInfo: ThemeUpdateInfo) => void>; + } + } + /** + * Namespace: browser.topSites + */ + namespace TopSites { + /** + * An object encapsulating a most visited URL, such as the URLs on the new tab page. + */ + interface MostVisitedURL { + /** + * The most visited URL. + */ + url: string; + /** + * The title of the page. + * Optional. + */ + title?: string; + /** + * Data URL for the favicon, if available. + * Optional. + */ + favicon?: string; + /** + * The entry type, either <code>url</code> for a normal page link, or <code>search</code> for a search shortcut. + * Optional. + */ + type?: MostVisitedURLTypeEnum; + } + interface GetOptionsType { + /** + * The number of top sites to return, defaults to the value used by Firefox + * Optional. + */ + limit?: number; + /** + * Limit the result to a single top site link per domain + * Optional. + */ + onePerDomain?: boolean; + /** + * Include sites that the user has blocked from appearing on the Firefox new tab. + * Optional. + */ + includeBlocked?: boolean; + /** + * Include sites favicon if available. + * Optional. + */ + includeFavicon?: boolean; + /** + * Include sites that the user has pinned on the Firefox new tab. + * Optional. + */ + includePinned?: boolean; + /** + * Include search shortcuts appearing on the Firefox new tab. + * Optional. + */ + includeSearchShortcuts?: boolean; + /** + * Return the sites that exactly appear on the user's new-tab page. When true, all other options are ignored except limit + * and includeFavicon. If the user disabled newtab Top Sites, the newtab parameter will be ignored. + * Optional. + */ + newtab?: boolean; + } + /** + * The entry type, either <code>url</code> for a normal page link, or <code>search</code> for a search shortcut. + */ + type MostVisitedURLTypeEnum = "url" | "search"; + interface Static { + /** + * Gets a list of top sites. + * + * @param options Optional. + */ + get(options?: GetOptionsType): Promise<MostVisitedURL[]>; + } + } + /** + * Namespace: browser.trial + */ + namespace Trial { + interface Static { + ml: Ml.Static; + } + } + /** + * Namespace: browser.types + */ + namespace Types { + /** + * The scope of the Setting. One of<ul><li><var>regular</var>: setting for the regular profile (which is inherited by the + * incognito profile if not overridden elsewhere),</li><li><var>regular_only</var>: setting for the regular profile only + * (not inherited by the incognito profile),</li><li><var>incognito_persistent</var>: setting for the incognito profile + * that survives browser restarts (overrides regular preferences),</li><li><var>incognito_session_only</var> + * : setting for the incognito profile that can only be set during an incognito session and is deleted when the incognito + * session ends (overrides regular and incognito_persistent preferences).</li></ul> Only <var>regular</var> + * is supported by Firefox at this time. + */ + type SettingScope = "regular" | "regular_only" | "incognito_persistent" | "incognito_session_only"; + /** + * One of<ul><li><var>not_controllable</var>: cannot be controlled by any extension</li><li><var> + * controlled_by_other_extensions</var>: controlled by extensions with higher precedence</li><li><var> + * controllable_by_this_extension</var>: can be controlled by this extension</li><li><var>controlled_by_this_extension</var> + * : controlled by this extension</li></ul> + */ + type LevelOfControl = "not_controllable" | "controlled_by_other_extensions" | "controllable_by_this_extension" | "controlled_by_this_extension"; + interface Setting { + /** + * Gets the value of a setting. + * + * @param details Which setting to consider. + */ + get(details: SettingGetDetailsType): Promise<SettingGetCallbackDetailsType>; + /** + * Sets the value of a setting. + * + * @param details Which setting to change. + * @returns Called at the completion of the set operation. + */ + set(details: SettingSetDetailsType): Promise<void>; + /** + * Clears the setting, restoring any default value. + * + * @param details Which setting to clear. + * @returns Called at the completion of the clear operation. + */ + clear(details: SettingClearDetailsType): Promise<void>; + /** + * Fired after the setting changes. + */ + onChange: Events.Event<(details: SettingOnChangeDetailsType) => void>; + } + interface SettingOnChangeDetailsType { + /** + * The value of the setting after the change. + */ + value: unknown; + /** + * The level of control of the setting. + */ + levelOfControl: Browser.Types.LevelOfControl; + /** + * Whether the value that has changed is specific to the incognito session.<br/>This property will <em>only</em> + * be present if the user has enabled the extension in incognito mode. + * Optional. + */ + incognitoSpecific?: boolean; + } + /** + * Which setting to consider. + */ + interface SettingGetDetailsType { + /** + * Whether to return the value that applies to the incognito session (default false). + * Optional. + */ + incognito?: boolean; + } + /** + * Details of the currently effective value. + */ + interface SettingGetCallbackDetailsType { + /** + * The value of the setting. + */ + value: unknown; + /** + * The level of control of the setting. + */ + levelOfControl: Browser.Types.LevelOfControl; + /** + * Whether the effective value is specific to the incognito session.<br/>This property will <em>only</em> + * be present if the <var>incognito</var> property in the <var>details</var> parameter of <code>get()</code> was true. + * Optional. + */ + incognitoSpecific?: boolean; + } + /** + * Which setting to change. + */ + interface SettingSetDetailsType { + /** + * The value of the setting. <br/>Note that every setting has a specific value type, which is described together with the + * setting. An extension should <em>not</em> set a value of a different type. + */ + value: unknown; + /** + * Where to set the setting (default: regular). + * Optional. + */ + scope?: Browser.Types.SettingScope; + } + /** + * Which setting to clear. + */ + interface SettingClearDetailsType { + /** + * Where to clear the setting (default: regular). + * Optional. + */ + scope?: Browser.Types.SettingScope; + } + interface Static { + [s: string]: unknown; + } + } + /** + * Namespace: browser.userScripts + */ + namespace UserScripts { + /** + * Details of a user script + */ + interface UserScriptOptions { + /** + * The list of JS files to inject + */ + js: Browser.ExtensionTypes.ExtensionFileOrCode[]; + /** + * An opaque user script metadata value + * Optional. + */ + scriptMetadata?: Browser.ExtensionTypes.PlainJSONValue; + matches: Browser.Manifest.MatchPattern[]; + /** + * Optional. + */ + excludeMatches?: Browser.Manifest.MatchPattern[]; + /** + * Optional. + */ + includeGlobs?: string[]; + /** + * Optional. + */ + excludeGlobs?: string[]; + /** + * If allFrames is <code>true</code>, implies that the JavaScript should be injected into all frames of current page. + * By default, it's <code>false</code> and is only injected into the top frame. + * Optional. + */ + allFrames?: boolean; + /** + * If matchAboutBlank is true, then the code is also injected in about:blank and about:srcdoc frames if your extension has + * access to its parent document. Code cannot be inserted in top-level about:-frames. By default it is <code>false</code>. + * Optional. + */ + matchAboutBlank?: boolean; + /** + * The soonest that the JavaScript will be injected into the tab. Defaults to "document_idle". + * Optional. + */ + runAt?: Browser.ExtensionTypes.RunAt; + /** + * limit the set of matched tabs to those that belong to the given cookie store id + * Optional. + */ + cookieStoreId?: string[] | string; + } + /** + * An object that represents a user script registered programmatically + */ + interface RegisteredUserScript { + /** + * The ID of the user script specified in the API call. This property must not start with a '_' as it's reserved as a + * prefix for generated script IDs. + */ + id: string; + /** + * If allFrames is <code>true</code>, implies that the JavaScript should be injected into all frames of current page. + * By default, it's <code>false</code> and is only injected into the top frame. + * Optional. + */ + allFrames?: boolean; + /** + * The list of ScriptSource objects defining sources of scripts to be injected into matching pages. + */ + js: ScriptSource[]; + /** + * At least one of matches or includeGlobs should be non-empty. The script runs in documents whose URL match either pattern. + * Optional. + */ + matches?: Browser.Manifest.MatchPattern[]; + /** + * Optional. + */ + excludeMatches?: Browser.Manifest.MatchPattern[]; + /** + * At least one of matches or includeGlobs should be non-empty. The script runs in documents whose URL match either pattern. + * Optional. + */ + includeGlobs?: string[]; + /** + * Optional. + */ + excludeGlobs?: string[]; + /** + * The soonest that the JavaScript will be injected into the tab. Defaults to "document_idle". + * Optional. + */ + runAt?: Browser.ExtensionTypes.RunAt; + /** + * The JavaScript script for a script to execute within. Defaults to "USER_SCRIPT". + * Optional. + */ + world?: ExecutionWorld; + /** + * If specified, specifies a specific user script world ID to execute in. Only valid if `world` is omitted or is + * `USER_SCRIPT`. If `worldId` is omitted, the script will execute in the default user script world (""). + * Values with leading underscores (`_`) are reserved. The maximum length is 256. + * Optional. + */ + worldId?: string; + } + /** + * The JavaScript world for a script to execute within. <code>USER_SCRIPT</code> is the default execution environment of + * user scripts, <code>MAIN</code> is the web page's execution environment. + */ + type ExecutionWorld = "MAIN" | "USER_SCRIPT"; + /** + * Optional filter to use with getScripts() and unregister(). + */ + interface UserScriptFilter { + /** + * Optional. + */ + ids?: string[]; + } + /** + * Object with file xor code property. Equivalent to the ExtensionFileOrCode, except the file remains a relative URL. + */ + type ScriptSource = ScriptSourceC1Type | ScriptSourceC2Type; + /** + * The configuration of a USER_SCRIPT world. + */ + interface WorldProperties { + /** + * The identifier of the world. Values with leading underscores (`_`) are reserved. The maximum length is 256. + * Defaults to the default USER_SCRIPT world (""). + * Optional. + */ + worldId?: string; + /** + * The world's Content Security Policy. Defaults to the CSP of regular content scripts, + * which prohibits dynamic code execution such as eval. + * Optional. + */ + csp?: string; + /** + * Whether the runtime.sendMessage and runtime.connect methods are exposed. Defaults to not exposing these messaging APIs. + * Optional. + */ + messaging?: boolean; + } + /** + * An object that represents a user script registered programmatically + */ + interface RegisterCallbackLegacyRegisteredUserScriptType { + /** + * Unregister a user script registered programmatically + */ + unregister(): Promise<void>; + } + interface UpdateScriptsItemType extends Omit<RegisteredUserScript, "js"> { + /** + * Optional. + */ + js?: ScriptSource[]; + } + interface ScriptSourceC1Type { + /** + * The path of the JavaScript file to inject relative to the extension's root directory. + */ + file: string; + } + interface ScriptSourceC2Type { + code: string; + } + interface Static { + /** + * Register a user script programmatically given its $(ref:userScripts.UserScriptOptions), + * and resolves to an object with the unregister() function + */ + register(userScriptOptions: UserScriptOptions): Promise<RegisterCallbackLegacyRegisteredUserScriptType>; + /** + * Registers one or more user scripts for this extension. + * + * @param scripts List of user scripts to be registered. + */ + register(scripts: RegisteredUserScript[]): void; + /** + * Updates one or more user scripts for this extension. + * + * @param scripts List of user scripts to be updated. + */ + update(scripts: UpdateScriptsItemType[]): void; + /** + * Unregisters all dynamically-registered user scripts for this extension. + * + * @param filter Optional. If specified, this method unregisters only the user scripts that match it. + */ + unregister(filter?: UserScriptFilter): void; + /** + * Returns all dynamically-registered user scripts for this extension. + * + * @param filter Optional. If specified, this method returns only the user scripts that match it. + */ + getScripts(filter?: UserScriptFilter): Promise<RegisteredUserScript[]>; + /** + * Configures the environment for scripts running in a USER_SCRIPT world. + * + * @param properties The desired configuration for a USER_SCRIPT world. + */ + configureWorld(properties: WorldProperties): void; + /** + * Resets the configuration for a given world. That world will fall back to the default world's configuration. + * + * @param worldId Optional. The ID of the USER_SCRIPT world to reset. If omitted or empty, + * resets the default world's configuration. + */ + resetWorldConfiguration(worldId?: string): void; + /** + * Returns all registered USER_SCRIPT world configurations. + */ + getWorldConfigurations(): Promise<WorldProperties[]>; + } + } + /** + * Namespace: browser.webNavigation + */ + namespace WebNavigation { + /** + * Cause of the navigation. The same transition types as defined in the history API are used. + * These are the same transition types as defined in the $(topic:transition_types)[history API] except with <code> + * "start_page"</code> in place of <code>"auto_toplevel"</code> (for backwards compatibility). + */ + type TransitionType = "link" | "typed" | "auto_bookmark" | "auto_subframe" | "manual_subframe" | "generated" | "start_page" | "form_submit" | "reload" | "keyword" | "keyword_generated"; + type TransitionQualifier = "client_redirect" | "server_redirect" | "forward_back" | "from_address_bar"; + interface EventUrlFilters { + url: Browser.Events.UrlFilter[]; + } + /** + * Information about the frame to retrieve information about. + */ + interface GetFrameDetailsType { + /** + * The ID of the tab in which the frame is. + */ + tabId: number; + /** + * The ID of the process runs the renderer for this tab. + * Optional. + */ + processId?: number; + /** + * The ID of the frame in the given tab. + */ + frameId: number; + } + /** + * Information about the requested frame, null if the specified frame ID and/or tab ID are invalid. + */ + interface GetFrameCallbackDetailsType { + /** + * True if the last navigation in this frame was interrupted by an error, i.e. the onErrorOccurred event fired. + * Optional. + */ + errorOccurred?: boolean; + /** + * The URL currently associated with this frame, if the frame identified by the frameId existed at one point in the given + * tab. The fact that an URL is associated with a given frameId does not imply that the corresponding frame still exists. + */ + url: string; + /** + * The ID of the tab in which the frame is. + */ + tabId: number; + /** + * The ID of the frame. 0 indicates that this is the main frame; a positive value indicates the ID of a subframe. + */ + frameId: number; + /** + * ID of frame that wraps the frame. Set to -1 of no parent frame exists. + */ + parentFrameId: number; + } + /** + * Information about the tab to retrieve all frames from. + */ + interface GetAllFramesDetailsType { + /** + * The ID of the tab. + */ + tabId: number; + } + interface GetAllFramesCallbackDetailsItemType { + /** + * True if the last navigation in this frame was interrupted by an error, i.e. the onErrorOccurred event fired. + * Optional. + */ + errorOccurred?: boolean; + /** + * The ID of the tab in which the frame is. + */ + tabId: number; + /** + * The ID of the frame. 0 indicates that this is the main frame; a positive value indicates the ID of a subframe. + */ + frameId: number; + /** + * ID of frame that wraps the frame. Set to -1 of no parent frame exists. + */ + parentFrameId: number; + /** + * The URL currently associated with this frame. + */ + url: string; + } + interface OnBeforeNavigateDetailsType { + /** + * The ID of the tab in which the navigation is about to occur. + */ + tabId: number; + url: string; + /** + * 0 indicates the navigation happens in the tab content window; a positive value indicates navigation in a subframe. + * Frame IDs are unique for a given tab and process. + */ + frameId: number; + /** + * ID of frame that wraps the frame. Set to -1 of no parent frame exists. + */ + parentFrameId: number; + /** + * The time when the browser was about to start the navigation, in milliseconds since the epoch. + */ + timeStamp: number; + } + interface OnCommittedDetailsType { + /** + * The ID of the tab in which the navigation occurs. + */ + tabId: number; + url: string; + /** + * 0 indicates the navigation happens in the tab content window; a positive value indicates navigation in a subframe. + * Frame IDs are unique within a tab. + */ + frameId: number; + /** + * Cause of the navigation. + */ + transitionType: TransitionType; + /** + * A list of transition qualifiers. + */ + transitionQualifiers: TransitionQualifier[]; + /** + * The time when the navigation was committed, in milliseconds since the epoch. + */ + timeStamp: number; + } + interface OnDOMContentLoadedDetailsType { + /** + * The ID of the tab in which the navigation occurs. + */ + tabId: number; + url: string; + /** + * 0 indicates the navigation happens in the tab content window; a positive value indicates navigation in a subframe. + * Frame IDs are unique within a tab. + */ + frameId: number; + /** + * The time when the page's DOM was fully constructed, in milliseconds since the epoch. + */ + timeStamp: number; + } + interface OnCompletedDetailsType { + /** + * The ID of the tab in which the navigation occurs. + */ + tabId: number; + url: string; + /** + * 0 indicates the navigation happens in the tab content window; a positive value indicates navigation in a subframe. + * Frame IDs are unique within a tab. + */ + frameId: number; + /** + * The time when the document finished loading, in milliseconds since the epoch. + */ + timeStamp: number; + } + interface OnErrorOccurredDetailsType { + /** + * The ID of the tab in which the navigation occurs. + */ + tabId: number; + url: string; + /** + * 0 indicates the navigation happens in the tab content window; a positive value indicates navigation in a subframe. + * Frame IDs are unique within a tab. + */ + frameId: number; + /** + * The time when the error occurred, in milliseconds since the epoch. + */ + timeStamp: number; + } + interface OnCreatedNavigationTargetDetailsType { + /** + * The ID of the tab in which the navigation is triggered. + */ + sourceTabId: number; + /** + * The ID of the process runs the renderer for the source tab. + */ + sourceProcessId: number; + /** + * The ID of the frame with sourceTabId in which the navigation is triggered. 0 indicates the main frame. + */ + sourceFrameId: number; + /** + * The URL to be opened in the new window. + */ + url: string; + /** + * The ID of the tab in which the url is opened + */ + tabId: number; + /** + * The time when the browser was about to create a new view, in milliseconds since the epoch. + */ + timeStamp: number; + } + interface OnReferenceFragmentUpdatedDetailsType { + /** + * The ID of the tab in which the navigation occurs. + */ + tabId: number; + url: string; + /** + * 0 indicates the navigation happens in the tab content window; a positive value indicates navigation in a subframe. + * Frame IDs are unique within a tab. + */ + frameId: number; + /** + * Cause of the navigation. + */ + transitionType: TransitionType; + /** + * A list of transition qualifiers. + */ + transitionQualifiers: TransitionQualifier[]; + /** + * The time when the navigation was committed, in milliseconds since the epoch. + */ + timeStamp: number; + } + interface OnTabReplacedDetailsType { + /** + * The ID of the tab that was replaced. + */ + replacedTabId: number; + /** + * The ID of the tab that replaced the old tab. + */ + tabId: number; + /** + * The time when the replacement happened, in milliseconds since the epoch. + */ + timeStamp: number; + } + interface OnHistoryStateUpdatedDetailsType { + /** + * The ID of the tab in which the navigation occurs. + */ + tabId: number; + url: string; + /** + * 0 indicates the navigation happens in the tab content window; a positive value indicates navigation in a subframe. + * Frame IDs are unique within a tab. + */ + frameId: number; + /** + * Cause of the navigation. + */ + transitionType: TransitionType; + /** + * A list of transition qualifiers. + */ + transitionQualifiers: TransitionQualifier[]; + /** + * The time when the navigation was committed, in milliseconds since the epoch. + */ + timeStamp: number; + } + /** + * Fired when a navigation is about to occur. + */ + interface OnBeforeNavigateEvent extends Events.Event<(details: OnBeforeNavigateDetailsType) => void> { + /** + * Registers an event listener <em>callback</em> to an event. + * + * @param callback Called when an event occurs. The parameters of this function depend on the type of event. + * @param filters Optional. Conditions that the URL being navigated to must satisfy. The 'schemes' and 'ports' fields of + * UrlFilter are ignored for this event. + */ + addListener(callback: (details: OnBeforeNavigateDetailsType) => void, filters?: EventUrlFilters): void; + } + /** + * Fired when a navigation is committed. The document (and the resources it refers to, such as images and subframes) + * might still be downloading, but at least part of the document has been received from the server and the browser has + * decided to switch to the new document. + */ + interface OnCommittedEvent extends Events.Event<(details: OnCommittedDetailsType) => void> { + /** + * Registers an event listener <em>callback</em> to an event. + * + * @param callback Called when an event occurs. The parameters of this function depend on the type of event. + * @param filters Optional. Conditions that the URL being navigated to must satisfy. The 'schemes' and 'ports' fields of + * UrlFilter are ignored for this event. + */ + addListener(callback: (details: OnCommittedDetailsType) => void, filters?: EventUrlFilters): void; + } + /** + * Fired when the page's DOM is fully constructed, but the referenced resources may not finish loading. + */ + interface OnDOMContentLoadedEvent extends Events.Event<(details: OnDOMContentLoadedDetailsType) => void> { + /** + * Registers an event listener <em>callback</em> to an event. + * + * @param callback Called when an event occurs. The parameters of this function depend on the type of event. + * @param filters Optional. Conditions that the URL being navigated to must satisfy. The 'schemes' and 'ports' fields of + * UrlFilter are ignored for this event. + */ + addListener(callback: (details: OnDOMContentLoadedDetailsType) => void, filters?: EventUrlFilters): void; + } + /** + * Fired when a document, including the resources it refers to, is completely loaded and initialized. + */ + interface OnCompletedEvent extends Events.Event<(details: OnCompletedDetailsType) => void> { + /** + * Registers an event listener <em>callback</em> to an event. + * + * @param callback Called when an event occurs. The parameters of this function depend on the type of event. + * @param filters Optional. Conditions that the URL being navigated to must satisfy. The 'schemes' and 'ports' fields of + * UrlFilter are ignored for this event. + */ + addListener(callback: (details: OnCompletedDetailsType) => void, filters?: EventUrlFilters): void; + } + /** + * Fired when an error occurs and the navigation is aborted. This can happen if either a network error occurred, + * or the user aborted the navigation. + */ + interface OnErrorOccurredEvent extends Events.Event<(details: OnErrorOccurredDetailsType) => void> { + /** + * Registers an event listener <em>callback</em> to an event. + * + * @param callback Called when an event occurs. The parameters of this function depend on the type of event. + * @param filters Optional. Conditions that the URL being navigated to must satisfy. The 'schemes' and 'ports' fields of + * UrlFilter are ignored for this event. + */ + addListener(callback: (details: OnErrorOccurredDetailsType) => void, filters?: EventUrlFilters): void; + } + /** + * Fired when a new window, or a new tab in an existing window, is created to host a navigation. + */ + interface OnCreatedNavigationTargetEvent extends Events.Event<(details: OnCreatedNavigationTargetDetailsType) => void> { + /** + * Registers an event listener <em>callback</em> to an event. + * + * @param callback Called when an event occurs. The parameters of this function depend on the type of event. + * @param filters Optional. Conditions that the URL being navigated to must satisfy. The 'schemes' and 'ports' fields of + * UrlFilter are ignored for this event. + */ + addListener(callback: (details: OnCreatedNavigationTargetDetailsType) => void, filters?: EventUrlFilters): void; + } + /** + * Fired when the reference fragment of a frame was updated. All future events for that frame will use the updated URL. + */ + interface OnReferenceFragmentUpdatedEvent extends Events.Event<(details: OnReferenceFragmentUpdatedDetailsType) => void> { + /** + * Registers an event listener <em>callback</em> to an event. + * + * @param callback Called when an event occurs. The parameters of this function depend on the type of event. + * @param filters Optional. Conditions that the URL being navigated to must satisfy. The 'schemes' and 'ports' fields of + * UrlFilter are ignored for this event. + */ + addListener(callback: (details: OnReferenceFragmentUpdatedDetailsType) => void, filters?: EventUrlFilters): void; + } + /** + * Fired when the frame's history was updated to a new URL. All future events for that frame will use the updated URL. + */ + interface OnHistoryStateUpdatedEvent extends Events.Event<(details: OnHistoryStateUpdatedDetailsType) => void> { + /** + * Registers an event listener <em>callback</em> to an event. + * + * @param callback Called when an event occurs. The parameters of this function depend on the type of event. + * @param filters Optional. Conditions that the URL being navigated to must satisfy. The 'schemes' and 'ports' fields of + * UrlFilter are ignored for this event. + */ + addListener(callback: (details: OnHistoryStateUpdatedDetailsType) => void, filters?: EventUrlFilters): void; + } + interface Static { + /** + * Retrieves information about the given frame. A frame refers to an <iframe> or a <frame> of a web page and is + * identified by a tab ID and a frame ID. + * + * @param details Information about the frame to retrieve information about. + */ + getFrame(details: GetFrameDetailsType): Promise<GetFrameCallbackDetailsType | null>; + /** + * Retrieves information about all frames of a given tab. + * + * @param details Information about the tab to retrieve all frames from. + */ + getAllFrames(details: GetAllFramesDetailsType): Promise<GetAllFramesCallbackDetailsItemType[] | null>; + /** + * Fired when a navigation is about to occur. + */ + onBeforeNavigate: OnBeforeNavigateEvent; + /** + * Fired when a navigation is committed. The document (and the resources it refers to, such as images and subframes) + * might still be downloading, but at least part of the document has been received from the server and the browser has + * decided to switch to the new document. + */ + onCommitted: OnCommittedEvent; + /** + * Fired when the page's DOM is fully constructed, but the referenced resources may not finish loading. + */ + onDOMContentLoaded: OnDOMContentLoadedEvent; + /** + * Fired when a document, including the resources it refers to, is completely loaded and initialized. + */ + onCompleted: OnCompletedEvent; + /** + * Fired when an error occurs and the navigation is aborted. This can happen if either a network error occurred, + * or the user aborted the navigation. + */ + onErrorOccurred: OnErrorOccurredEvent; + /** + * Fired when a new window, or a new tab in an existing window, is created to host a navigation. + */ + onCreatedNavigationTarget: OnCreatedNavigationTargetEvent; + /** + * Fired when the reference fragment of a frame was updated. All future events for that frame will use the updated URL. + */ + onReferenceFragmentUpdated: OnReferenceFragmentUpdatedEvent; + /** + * Fired when the contents of the tab is replaced by a different (usually previously pre-rendered) tab. + */ + onTabReplaced: Events.Event<(details: OnTabReplacedDetailsType) => void>; + /** + * Fired when the frame's history was updated to a new URL. All future events for that frame will use the updated URL. + */ + onHistoryStateUpdated: OnHistoryStateUpdatedEvent; + } + } + /** + * Namespace: browser.webRequest + */ + namespace WebRequest { + type ResourceType = "main_frame" | "sub_frame" | "stylesheet" | "script" | "image" | "object" | "xmlhttprequest" | "xslt" | "ping" | "beacon" | "xml_dtd" | "font" | "media" | "websocket" | "csp_report" | "imageset" | "web_manifest" | "speculative" | "json" | "other"; + type OnBeforeRequestOptions = "blocking" | "requestBody" | "extraHeaders"; + type OnBeforeSendHeadersOptions = "requestHeaders" | "blocking" | "extraHeaders"; + type OnSendHeadersOptions = "requestHeaders" | "extraHeaders"; + type OnHeadersReceivedOptions = "blocking" | "responseHeaders" | "extraHeaders"; + type OnAuthRequiredOptions = "responseHeaders" | "blocking" | "asyncBlocking" | "extraHeaders"; + type OnResponseStartedOptions = "responseHeaders" | "extraHeaders"; + type OnBeforeRedirectOptions = "responseHeaders" | "extraHeaders"; + type OnCompletedOptions = "responseHeaders" | "extraHeaders"; + /** + * An object describing filters to apply to webRequest events. + */ + interface RequestFilter { + /** + * A list of URLs or URL patterns. Requests that cannot match any of the URLs will be filtered out. + */ + urls: string[]; + /** + * A list of request types. Requests that cannot match any of the types will be filtered out. + * Optional. + */ + types?: ResourceType[]; + /** + * Optional. + */ + tabId?: number; + /** + * Optional. + */ + windowId?: number; + /** + * If provided, requests that do not match the incognito state will be filtered out. + * Optional. + */ + incognito?: boolean; + } + /** + * An array of HTTP headers. Each header is represented as a dictionary containing the keys <code>name</code> + * and either <code>value</code> or <code>binaryValue</code>. + */ + type HttpHeaders = HttpHeadersItemType[]; + /** + * Returns value for event handlers that have the 'blocking' extraInfoSpec applied. Allows the event handler to modify + * network requests. + */ + interface BlockingResponse { + /** + * If true, the request is cancelled. Used in onBeforeRequest, this prevents the request from being sent. + * Optional. + */ + cancel?: boolean; + /** + * Only used as a response to the onBeforeRequest and onHeadersReceived events. If set, + * the original request is prevented from being sent/completed and is instead redirected to the given URL. + * Redirections to non-HTTP schemes such as data: are allowed. Redirects initiated by a redirect action use the original + * request method for the redirect, with one exception: If the redirect is initiated at the onHeadersReceived stage, + * then the redirect will be issued using the GET method. + * Optional. + */ + redirectUrl?: string; + /** + * Only used as a response to the onBeforeRequest event. If set, the original request is prevented from being + * sent/completed and is instead upgraded to a secure request. If any extension returns <code>redirectUrl</code> + * during onBeforeRequest, <code>upgradeToSecure</code> will have no affect. + * Optional. + */ + upgradeToSecure?: boolean; + /** + * Only used as a response to the onBeforeSendHeaders event. If set, the request is made with these request headers instead. + * Optional. + */ + requestHeaders?: HttpHeaders; + /** + * Only used as a response to the onHeadersReceived event. If set, the server is assumed to have responded with these + * response headers instead. Only return <code>responseHeaders</code> if you really want to modify the headers in order to + * limit the number of conflicts (only one extension may modify <code>responseHeaders</code> for each request). + * Optional. + */ + responseHeaders?: HttpHeaders; + /** + * Only used as a response to the onAuthRequired event. If set, the request is made using the supplied credentials. + * Optional. + */ + authCredentials?: BlockingResponseAuthCredentialsType; + } + /** + * Contains the certificate properties of the request if it is a secure request. + */ + interface CertificateInfo { + subject: string; + issuer: string; + /** + * Contains start and end timestamps. + */ + validity: CertificateInfoValidityType; + fingerprint: CertificateInfoFingerprintType; + serialNumber: string; + isBuiltInRoot: boolean; + subjectPublicKeyInfoDigest: CertificateInfoSubjectPublicKeyInfoDigestType; + /** + * Optional. + */ + rawDER?: number[]; + } + type CertificateTransparencyStatus = "not_applicable" | "policy_compliant" | "policy_not_enough_scts" | "policy_not_diverse_scts"; + type TransportWeaknessReasons = "cipher"; + /** + * Contains the security properties of the request (ie. SSL/TLS information). + */ + interface SecurityInfo { + state: SecurityInfoStateEnum; + /** + * Error message if state is "broken" + * Optional. + */ + errorMessage?: string; + /** + * Protocol version if state is "secure" + * Optional. + */ + protocolVersion?: SecurityInfoProtocolVersionEnum; + /** + * The cipher suite used in this request if state is "secure". + * Optional. + */ + cipherSuite?: string; + /** + * The key exchange algorithm used in this request if state is "secure". + * Optional. + */ + keaGroupName?: string; + /** + * The length (in bits) of the secret key. + * Optional. + */ + secretKeyLength?: number; + /** + * The signature scheme used in this request if state is "secure". + * Optional. + */ + signatureSchemeName?: string; + /** + * Certificate data if state is "secure". Will only contain one entry unless <code>certificateChain</code> + * is passed as an option. + */ + certificates: CertificateInfo[]; + /** + * The type of certificate error that was overridden for this connection, if any. + * Optional. + */ + overridableErrorCategory?: SecurityInfoOverridableErrorCategoryEnum; + /** + * Optional. + */ + isExtendedValidation?: boolean; + /** + * Certificate transparency compliance per RFC 6962. See <code>https://www.certificate-transparency.org/what-is-ct</code> + * for more information. + * Optional. + */ + certificateTransparencyStatus?: CertificateTransparencyStatus; + /** + * True if host uses Strict Transport Security and state is "secure". + * Optional. + */ + hsts?: boolean; + /** + * True if host uses Public Key Pinning and state is "secure". + * Optional. + */ + hpkp?: string; + /** + * list of reasons that cause the request to be considered weak, if state is "weak" + * Optional. + */ + weaknessReasons?: TransportWeaknessReasons[]; + /** + * True if the TLS connection used Encrypted Client Hello. + * Optional. + */ + usedEch?: boolean; + /** + * True if the TLS connection used Delegated Credentials. + * Optional. + */ + usedDelegatedCredentials?: boolean; + /** + * True if the TLS connection made OCSP requests. + * Optional. + */ + usedOcsp?: boolean; + /** + * True if the TLS connection used a privacy-preserving DNS transport like DNS-over-HTTPS. + * Optional. + */ + usedPrivateDns?: boolean; + } + /** + * Contains data uploaded in a URL request. + */ + interface UploadData { + /** + * An ArrayBuffer with a copy of the data. + * Optional. + */ + bytes?: unknown; + /** + * A string with the file's path and name. + * Optional. + */ + file?: string; + } + /** + * Tracking flags that match our internal tracking classification + */ + type UrlClassificationFlags = "fingerprinting" | "fingerprinting_content" | "cryptomining" | "cryptomining_content" | "emailtracking" | "emailtracking_content" | "consentmanager" | "tracking" | "tracking_ad" | "tracking_analytics" | "tracking_social" | "tracking_content" | "any_basic_tracking" | "any_strict_tracking" | "any_social_tracking"; + /** + * If the request has been classified this is an array of $(ref:UrlClassificationFlags). + */ + type UrlClassificationParty = UrlClassificationFlags[]; + interface UrlClassification { + /** + * Classification flags if the request has been classified and it is first party. + */ + firstParty: UrlClassificationParty; + /** + * Classification flags if the request has been classified and it or its window hierarchy is third party. + */ + thirdParty: UrlClassificationParty; + } + type OnErrorOccurredOptions = "extraHeaders"; + /** + * A BlockingResponse or a Promise<BlockingResponse> + */ + // eslint-disable-next-line @typescript-eslint/no-invalid-void-type + type BlockingResponseOrPromiseOrVoid = BlockingResponse | Promise<BlockingResponse> | void; + /** + * "uninitialized": The StreamFilter is not fully initialized. No methods may be called until a "start" event has been + * received. + * "transferringdata": The underlying channel is currently transferring data, which will be dispatched via "data" events. + * "finishedtransferringdata": The underlying channel has finished transferring data. Data may still be written via write() + * calls at this point. + * "suspended": Data transfer is currently suspended. It may be resumed by a call to resume(). + * Data may still be written via write() calls in this state. + * "closed": The channel has been closed by a call to close(). No further data wlil be delivered via "data" events, + * and no further data may be written via write() calls. + * "disconnected": The channel has been disconnected by a call to disconnect(). All further data will be delivered directly, + * without passing through the filter. No further events will be dispatched, and no further data may be written by write() + * calls. + * "failed": An error has occurred and the channel is disconnected. The `error`, property contains the details of the error. + */ + type StreamFilterStatus = "uninitialized" | "transferringdata" | "finishedtransferringdata" | "suspended" | "closed" | "disconnected" | "failed"; + /** + * An interface which allows an extension to intercept, and optionally modify, response data from an HTTP request. + */ + interface StreamFilter { + /** + * Returns the current status of the stream. + */ + status: StreamFilterStatus; + /** + * After an "error" event has been dispatched, this contains a message describing the error. + */ + error: string; + /** + * Creates a stream filter for the given add-on and the given extension ID. + */ + create(requestId: number, addonId: string): void; + /** + * Suspends processing of the request. After this is called, no further data will be delivered until the request is resumed. + */ + suspend(): void; + /** + * Resumes delivery of data for a suspended request. + */ + resume(): void; + /** + * Closes the request. After this is called, no more data may be written to the stream, + * and no further data will be delivered. This *must* be called after the consumer is finished writing data, + * unless disconnect() has already been called. + */ + close(): void; + /** + * Disconnects the stream filter from the request. After this is called, no further data will be delivered to the filter, + * and any unprocessed data will be written directly to the output stream. + */ + disconnect(): void; + /** + * Writes a chunk of data to the output stream. This may not be called before the "start" event has been received. + */ + write(data: ArrayBuffer | Uint8Array): void; + /** + * Dispatched with a StreamFilterDataEvent whenever incoming data is available on the stream. + * This data will not be delivered to the output stream unless it is explicitly written via a write() call. + */ + ondata?: (data: StreamFilterEventData) => void; + /** + * Dispatched when the stream is opened, and is about to begin delivering data. + */ + onstart?: (data: StreamFilterEventData) => void; + /** + * Dispatched when the stream has closed, and has no more data to deliver. The output stream remains open and writable + * until close() is called. + */ + onstop?: (data: StreamFilterEventData) => void; + /** + * Dispatched when an error has occurred. No further data may be read or written after this point. + */ + onerror?: (data: StreamFilterEventData) => void; + } + interface StreamFilterEventData { + /** + * Contains a chunk of data read from the input stream. + */ + data: ArrayBuffer; + } + interface GetSecurityInfoOptionsType { + /** + * Include the entire certificate chain. + * Optional. + */ + certificateChain?: boolean; + /** + * Include raw certificate data for processing by the extension. + * Optional. + */ + rawDER?: boolean; + } + interface OnBeforeRequestDetailsType { + /** + * The ID of the request. Request IDs are unique within a browser session. As a result, + * they could be used to relate different events of the same request. + */ + requestId: string; + url: string; + /** + * Standard HTTP method. + */ + method: string; + /** + * The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in + * which the request happens. If the document of a (sub-)frame is loaded (<code>type</code> is <code>main_frame</code> + * or <code>sub_frame</code>), <code>frameId</code> indicates the ID of this frame, not the ID of the outer frame. + * Frame IDs are unique within a tab. + */ + frameId: number; + /** + * ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists. + */ + parentFrameId: number; + /** + * True for private browsing requests. + * Optional. + */ + incognito?: boolean; + /** + * The cookie store ID of the contextual identity. + * Optional. + */ + cookieStoreId?: string; + /** + * URL of the resource that triggered this request. + * Optional. + */ + originUrl?: string; + /** + * URL of the page into which the requested resource will be loaded. + * Optional. + */ + documentUrl?: string; + /** + * Contains the HTTP request body data. Only provided if extraInfoSpec contains 'requestBody'. + * Optional. + */ + requestBody?: OnBeforeRequestDetailsTypeRequestBodyType; + /** + * The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab. + */ + tabId: number; + /** + * How the requested resource will be used. + */ + type: ResourceType; + /** + * The time when this signal is triggered, in milliseconds since the epoch. + */ + timeStamp: number; + /** + * Tracking classification if the request has been classified. + * Optional. + */ + urlClassification?: UrlClassification; + /** + * Indicates if this request and its content window hierarchy is third party. + */ + thirdParty: boolean; + /** + * URL of the resource that triggered this request (on chrome). + * Optional. + */ + initiator?: string; + } + interface OnBeforeSendHeadersDetailsType { + /** + * The ID of the request. Request IDs are unique within a browser session. As a result, + * they could be used to relate different events of the same request. + */ + requestId: string; + url: string; + /** + * Standard HTTP method. + */ + method: string; + /** + * The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in + * which the request happens. If the document of a (sub-)frame is loaded (<code>type</code> is <code>main_frame</code> + * or <code>sub_frame</code>), <code>frameId</code> indicates the ID of this frame, not the ID of the outer frame. + * Frame IDs are unique within a tab. + */ + frameId: number; + /** + * ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists. + */ + parentFrameId: number; + /** + * True for private browsing requests. + * Optional. + */ + incognito?: boolean; + /** + * The cookie store ID of the contextual identity. + * Optional. + */ + cookieStoreId?: string; + /** + * URL of the resource that triggered this request. + * Optional. + */ + originUrl?: string; + /** + * URL of the page into which the requested resource will be loaded. + * Optional. + */ + documentUrl?: string; + /** + * The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab. + */ + tabId: number; + /** + * How the requested resource will be used. + */ + type: ResourceType; + /** + * The time when this signal is triggered, in milliseconds since the epoch. + */ + timeStamp: number; + /** + * The HTTP request headers that are going to be sent out with this request. + * Optional. + */ + requestHeaders?: HttpHeaders; + /** + * Tracking classification if the request has been classified. + * Optional. + */ + urlClassification?: UrlClassification; + /** + * Indicates if this request and its content window hierarchy is third party. + */ + thirdParty: boolean; + /** + * URL of the resource that triggered this request (on chrome). + * Optional. + */ + initiator?: string; + } + interface OnSendHeadersDetailsType { + /** + * The ID of the request. Request IDs are unique within a browser session. As a result, + * they could be used to relate different events of the same request. + */ + requestId: string; + url: string; + /** + * Standard HTTP method. + */ + method: string; + /** + * The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in + * which the request happens. If the document of a (sub-)frame is loaded (<code>type</code> is <code>main_frame</code> + * or <code>sub_frame</code>), <code>frameId</code> indicates the ID of this frame, not the ID of the outer frame. + * Frame IDs are unique within a tab. + */ + frameId: number; + /** + * ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists. + */ + parentFrameId: number; + /** + * True for private browsing requests. + * Optional. + */ + incognito?: boolean; + /** + * The cookie store ID of the contextual identity. + * Optional. + */ + cookieStoreId?: string; + /** + * URL of the resource that triggered this request. + * Optional. + */ + originUrl?: string; + /** + * URL of the page into which the requested resource will be loaded. + * Optional. + */ + documentUrl?: string; + /** + * The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab. + */ + tabId: number; + /** + * How the requested resource will be used. + */ + type: ResourceType; + /** + * The time when this signal is triggered, in milliseconds since the epoch. + */ + timeStamp: number; + /** + * The HTTP request headers that have been sent out with this request. + * Optional. + */ + requestHeaders?: HttpHeaders; + /** + * Tracking classification if the request has been classified. + * Optional. + */ + urlClassification?: UrlClassification; + /** + * Indicates if this request and its content window hierarchy is third party. + */ + thirdParty: boolean; + /** + * URL of the resource that triggered this request (on chrome). + * Optional. + */ + initiator?: string; + } + interface OnHeadersReceivedDetailsType { + /** + * The ID of the request. Request IDs are unique within a browser session. As a result, + * they could be used to relate different events of the same request. + */ + requestId: string; + url: string; + /** + * Standard HTTP method. + */ + method: string; + /** + * The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in + * which the request happens. If the document of a (sub-)frame is loaded (<code>type</code> is <code>main_frame</code> + * or <code>sub_frame</code>), <code>frameId</code> indicates the ID of this frame, not the ID of the outer frame. + * Frame IDs are unique within a tab. + */ + frameId: number; + /** + * ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists. + */ + parentFrameId: number; + /** + * True for private browsing requests. + * Optional. + */ + incognito?: boolean; + /** + * The cookie store ID of the contextual identity. + * Optional. + */ + cookieStoreId?: string; + /** + * URL of the resource that triggered this request. + * Optional. + */ + originUrl?: string; + /** + * URL of the page into which the requested resource will be loaded. + * Optional. + */ + documentUrl?: string; + /** + * The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab. + */ + tabId: number; + /** + * How the requested resource will be used. + */ + type: ResourceType; + /** + * The time when this signal is triggered, in milliseconds since the epoch. + */ + timeStamp: number; + /** + * HTTP status line of the response or the 'HTTP/0.9 200 OK' string for HTTP/0.9 responses (i.e., + * responses that lack a status line). + */ + statusLine: string; + /** + * The HTTP response headers that have been received with this response. + * Optional. + */ + responseHeaders?: HttpHeaders; + /** + * Standard HTTP status code returned by the server. + */ + statusCode: number; + /** + * Tracking classification if the request has been classified. + * Optional. + */ + urlClassification?: UrlClassification; + /** + * Indicates if this request and its content window hierarchy is third party. + */ + thirdParty: boolean; + /** + * URL of the resource that triggered this request (on chrome). + * Optional. + */ + initiator?: string; + } + interface OnAuthRequiredDetailsType { + /** + * The ID of the request. Request IDs are unique within a browser session. As a result, + * they could be used to relate different events of the same request. + */ + requestId: string; + url: string; + /** + * Standard HTTP method. + */ + method: string; + /** + * The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in + * which the request happens. If the document of a (sub-)frame is loaded (<code>type</code> is <code>main_frame</code> + * or <code>sub_frame</code>), <code>frameId</code> indicates the ID of this frame, not the ID of the outer frame. + * Frame IDs are unique within a tab. + */ + frameId: number; + /** + * ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists. + */ + parentFrameId: number; + /** + * True for private browsing requests. + * Optional. + */ + incognito?: boolean; + /** + * The cookie store ID of the contextual identity. + * Optional. + */ + cookieStoreId?: string; + /** + * URL of the resource that triggered this request. + * Optional. + */ + originUrl?: string; + /** + * URL of the page into which the requested resource will be loaded. + * Optional. + */ + documentUrl?: string; + /** + * The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab. + */ + tabId: number; + /** + * How the requested resource will be used. + */ + type: ResourceType; + /** + * The time when this signal is triggered, in milliseconds since the epoch. + */ + timeStamp: number; + /** + * The authentication scheme, e.g. Basic or Digest. + */ + scheme: string; + /** + * The authentication realm provided by the server, if there is one. + * Optional. + */ + realm?: string; + /** + * The server requesting authentication. + */ + challenger: OnAuthRequiredDetailsTypeChallengerType; + /** + * True for Proxy-Authenticate, false for WWW-Authenticate. + */ + isProxy: boolean; + /** + * The HTTP response headers that were received along with this response. + * Optional. + */ + responseHeaders?: HttpHeaders; + /** + * HTTP status line of the response or the 'HTTP/0.9 200 OK' string for HTTP/0.9 responses (i.e., + * responses that lack a status line) or an empty string if there are no headers. + */ + statusLine: string; + /** + * Standard HTTP status code returned by the server. + */ + statusCode: number; + /** + * Tracking classification if the request has been classified. + * Optional. + */ + urlClassification?: UrlClassification; + /** + * Indicates if this request and its content window hierarchy is third party. + */ + thirdParty: boolean; + /** + * URL of the resource that triggered this request (on chrome). + * Optional. + */ + initiator?: string; + } + interface OnResponseStartedDetailsType { + /** + * The ID of the request. Request IDs are unique within a browser session. As a result, + * they could be used to relate different events of the same request. + */ + requestId: string; + url: string; + /** + * Standard HTTP method. + */ + method: string; + /** + * The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in + * which the request happens. If the document of a (sub-)frame is loaded (<code>type</code> is <code>main_frame</code> + * or <code>sub_frame</code>), <code>frameId</code> indicates the ID of this frame, not the ID of the outer frame. + * Frame IDs are unique within a tab. + */ + frameId: number; + /** + * ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists. + */ + parentFrameId: number; + /** + * True for private browsing requests. + * Optional. + */ + incognito?: boolean; + /** + * The cookie store ID of the contextual identity. + * Optional. + */ + cookieStoreId?: string; + /** + * URL of the resource that triggered this request. + * Optional. + */ + originUrl?: string; + /** + * URL of the page into which the requested resource will be loaded. + * Optional. + */ + documentUrl?: string; + /** + * The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab. + */ + tabId: number; + /** + * How the requested resource will be used. + */ + type: ResourceType; + /** + * The time when this signal is triggered, in milliseconds since the epoch. + */ + timeStamp: number; + /** + * The server IP address that the request was actually sent to. Note that it may be a literal IPv6 address. + * Optional. + */ + ip?: string; + /** + * Indicates if this response was fetched from disk cache. + */ + fromCache: boolean; + /** + * Standard HTTP status code returned by the server. + */ + statusCode: number; + /** + * The HTTP response headers that were received along with this response. + * Optional. + */ + responseHeaders?: HttpHeaders; + /** + * HTTP status line of the response or the 'HTTP/0.9 200 OK' string for HTTP/0.9 responses (i.e., + * responses that lack a status line) or an empty string if there are no headers. + */ + statusLine: string; + /** + * Tracking classification if the request has been classified. + * Optional. + */ + urlClassification?: UrlClassification; + /** + * Indicates if this request and its content window hierarchy is third party. + */ + thirdParty: boolean; + /** + * URL of the resource that triggered this request (on chrome). + * Optional. + */ + initiator?: string; + } + interface OnBeforeRedirectDetailsType { + /** + * The ID of the request. Request IDs are unique within a browser session. As a result, + * they could be used to relate different events of the same request. + */ + requestId: string; + url: string; + /** + * Standard HTTP method. + */ + method: string; + /** + * The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in + * which the request happens. If the document of a (sub-)frame is loaded (<code>type</code> is <code>main_frame</code> + * or <code>sub_frame</code>), <code>frameId</code> indicates the ID of this frame, not the ID of the outer frame. + * Frame IDs are unique within a tab. + */ + frameId: number; + /** + * ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists. + */ + parentFrameId: number; + /** + * True for private browsing requests. + * Optional. + */ + incognito?: boolean; + /** + * The cookie store ID of the contextual identity. + * Optional. + */ + cookieStoreId?: string; + /** + * URL of the resource that triggered this request. + * Optional. + */ + originUrl?: string; + /** + * URL of the page into which the requested resource will be loaded. + * Optional. + */ + documentUrl?: string; + /** + * The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab. + */ + tabId: number; + /** + * How the requested resource will be used. + */ + type: ResourceType; + /** + * The time when this signal is triggered, in milliseconds since the epoch. + */ + timeStamp: number; + /** + * The server IP address that the request was actually sent to. Note that it may be a literal IPv6 address. + * Optional. + */ + ip?: string; + /** + * Indicates if this response was fetched from disk cache. + */ + fromCache: boolean; + /** + * Standard HTTP status code returned by the server. + */ + statusCode: number; + /** + * The new URL. + */ + redirectUrl: string; + /** + * The HTTP response headers that were received along with this redirect. + * Optional. + */ + responseHeaders?: HttpHeaders; + /** + * HTTP status line of the response or the 'HTTP/0.9 200 OK' string for HTTP/0.9 responses (i.e., + * responses that lack a status line) or an empty string if there are no headers. + */ + statusLine: string; + /** + * Tracking classification if the request has been classified. + * Optional. + */ + urlClassification?: UrlClassification; + /** + * Indicates if this request and its content window hierarchy is third party. + */ + thirdParty: boolean; + /** + * URL of the resource that triggered this request (on chrome). + * Optional. + */ + initiator?: string; + } + interface OnCompletedDetailsType { + /** + * The ID of the request. Request IDs are unique within a browser session. As a result, + * they could be used to relate different events of the same request. + */ + requestId: string; + url: string; + /** + * Standard HTTP method. + */ + method: string; + /** + * The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in + * which the request happens. If the document of a (sub-)frame is loaded (<code>type</code> is <code>main_frame</code> + * or <code>sub_frame</code>), <code>frameId</code> indicates the ID of this frame, not the ID of the outer frame. + * Frame IDs are unique within a tab. + */ + frameId: number; + /** + * ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists. + */ + parentFrameId: number; + /** + * True for private browsing requests. + * Optional. + */ + incognito?: boolean; + /** + * The cookie store ID of the contextual identity. + * Optional. + */ + cookieStoreId?: string; + /** + * URL of the resource that triggered this request. + * Optional. + */ + originUrl?: string; + /** + * URL of the page into which the requested resource will be loaded. + * Optional. + */ + documentUrl?: string; + /** + * The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab. + */ + tabId: number; + /** + * How the requested resource will be used. + */ + type: ResourceType; + /** + * The time when this signal is triggered, in milliseconds since the epoch. + */ + timeStamp: number; + /** + * The server IP address that the request was actually sent to. Note that it may be a literal IPv6 address. + * Optional. + */ + ip?: string; + /** + * Indicates if this response was fetched from disk cache. + */ + fromCache: boolean; + /** + * Standard HTTP status code returned by the server. + */ + statusCode: number; + /** + * The HTTP response headers that were received along with this response. + * Optional. + */ + responseHeaders?: HttpHeaders; + /** + * HTTP status line of the response or the 'HTTP/0.9 200 OK' string for HTTP/0.9 responses (i.e., + * responses that lack a status line) or an empty string if there are no headers. + */ + statusLine: string; + /** + * Tracking classification if the request has been classified. + */ + urlClassification: UrlClassification; + /** + * Indicates if this request and its content window hierarchy is third party. + */ + thirdParty: boolean; + /** + * For http requests, the bytes transferred in the request. Only available in onCompleted. + */ + requestSize: number; + /** + * For http requests, the bytes received in the request. Only available in onCompleted. + */ + responseSize: number; + /** + * URL of the resource that triggered this request (on chrome). + * Optional. + */ + initiator?: string; + } + interface OnErrorOccurredDetailsType { + /** + * The ID of the request. Request IDs are unique within a browser session. As a result, + * they could be used to relate different events of the same request. + */ + requestId: string; + url: string; + /** + * Standard HTTP method. + */ + method: string; + /** + * The value 0 indicates that the request happens in the main frame; a positive value indicates the ID of a subframe in + * which the request happens. If the document of a (sub-)frame is loaded (<code>type</code> is <code>main_frame</code> + * or <code>sub_frame</code>), <code>frameId</code> indicates the ID of this frame, not the ID of the outer frame. + * Frame IDs are unique within a tab. + */ + frameId: number; + /** + * ID of frame that wraps the frame which sent the request. Set to -1 if no parent frame exists. + */ + parentFrameId: number; + /** + * True for private browsing requests. + * Optional. + */ + incognito?: boolean; + /** + * The cookie store ID of the contextual identity. + * Optional. + */ + cookieStoreId?: string; + /** + * URL of the resource that triggered this request. + * Optional. + */ + originUrl?: string; + /** + * URL of the page into which the requested resource will be loaded. + * Optional. + */ + documentUrl?: string; + /** + * The ID of the tab in which the request takes place. Set to -1 if the request isn't related to a tab. + */ + tabId: number; + /** + * How the requested resource will be used. + */ + type: ResourceType; + /** + * The time when this signal is triggered, in milliseconds since the epoch. + */ + timeStamp: number; + /** + * The server IP address that the request was actually sent to. Note that it may be a literal IPv6 address. + * Optional. + */ + ip?: string; + /** + * Indicates if this response was fetched from disk cache. + */ + fromCache: boolean; + /** + * The error description. This string is <em>not</em> guaranteed to remain backwards compatible between releases. + * You must not parse and act based upon its content. + */ + error: string; + /** + * Tracking classification if the request has been classified. + * Optional. + */ + urlClassification?: UrlClassification; + /** + * Indicates if this request and its content window hierarchy is third party. + */ + thirdParty: boolean; + /** + * URL of the resource that triggered this request (on chrome). + * Optional. + */ + initiator?: string; + } + interface HttpHeadersItemType { + /** + * Name of the HTTP header. + */ + name: string; + /** + * Value of the HTTP header if it can be represented by UTF-8. + * Optional. + */ + value?: string; + /** + * Value of the HTTP header if it cannot be represented by UTF-8, stored as individual byte values (0..255). + * Optional. + */ + binaryValue?: number[]; + } + /** + * Only used as a response to the onAuthRequired event. If set, the request is made using the supplied credentials. + */ + interface BlockingResponseAuthCredentialsType { + username: string; + password: string; + } + /** + * Contains start and end timestamps. + */ + interface CertificateInfoValidityType { + start: number; + end: number; + } + interface CertificateInfoFingerprintType { + sha1: string; + sha256: string; + } + interface CertificateInfoSubjectPublicKeyInfoDigestType { + sha256: string; + } + type SecurityInfoStateEnum = "insecure" | "weak" | "broken" | "secure"; + /** + * Protocol version if state is "secure" + */ + type SecurityInfoProtocolVersionEnum = "TLSv1" | "TLSv1.1" | "TLSv1.2" | "TLSv1.3" | "unknown"; + /** + * The type of certificate error that was overridden for this connection, if any. + */ + type SecurityInfoOverridableErrorCategoryEnum = "trust_error" | "domain_mismatch" | "expired_or_not_yet_valid"; + /** + * Contains the HTTP request body data. Only provided if extraInfoSpec contains 'requestBody'. + */ + interface OnBeforeRequestDetailsTypeRequestBodyType { + /** + * Errors when obtaining request body data. + * Optional. + */ + error?: string; + /** + * If the request method is POST and the body is a sequence of key-value pairs encoded in UTF8, + * encoded as either multipart/form-data, or application/x-www-form-urlencoded, this dictionary is present and for each + * key contains the list of all values for that key. If the data is of another media type, or if it is malformed, + * the dictionary is not present. An example value of this dictionary is {'key': ['value1', 'value2']}. + * Optional. + */ + formData?: Record<string, string>; + /** + * If the request method is PUT or POST, and the body is not already parsed in formData, + * then the unparsed request body elements are contained in this array. + * Optional. + */ + raw?: UploadData[]; + } + /** + * The server requesting authentication. + */ + interface OnAuthRequiredDetailsTypeChallengerType { + host: string; + port: number; + } + /** + * Fired when a request is about to occur. + */ + interface OnBeforeRequestEvent extends Events.Event<(details: OnBeforeRequestDetailsType) => BlockingResponseOrPromiseOrVoid> { + /** + * Registers an event listener <em>callback</em> to an event. + * + * @param callback Called when an event occurs. The parameters of this function depend on the type of event. + * @param filter A set of filters that restricts the events that will be sent to this listener. + * @param extraInfoSpec Optional. Array of extra information that should be passed to the listener function. + */ + addListener(callback: (details: OnBeforeRequestDetailsType) => BlockingResponseOrPromiseOrVoid, filter: RequestFilter, extraInfoSpec?: OnBeforeRequestOptions[]): void; + } + /** + * Fired before sending an HTTP request, once the request headers are available. This may occur after a TCP connection is + * made to the server, but before any HTTP data is sent. + */ + interface OnBeforeSendHeadersEvent extends Events.Event<(details: OnBeforeSendHeadersDetailsType) => BlockingResponseOrPromiseOrVoid> { + /** + * Registers an event listener <em>callback</em> to an event. + * + * @param callback Called when an event occurs. The parameters of this function depend on the type of event. + * @param filter A set of filters that restricts the events that will be sent to this listener. + * @param extraInfoSpec Optional. Array of extra information that should be passed to the listener function. + */ + addListener(callback: (details: OnBeforeSendHeadersDetailsType) => BlockingResponseOrPromiseOrVoid, filter: RequestFilter, extraInfoSpec?: OnBeforeSendHeadersOptions[]): void; + } + /** + * Fired just before a request is going to be sent to the server (modifications of previous onBeforeSendHeaders callbacks + * are visible by the time onSendHeaders is fired). + */ + interface OnSendHeadersEvent extends Events.Event<(details: OnSendHeadersDetailsType) => void> { + /** + * Registers an event listener <em>callback</em> to an event. + * + * @param callback Called when an event occurs. The parameters of this function depend on the type of event. + * @param filter A set of filters that restricts the events that will be sent to this listener. + * @param extraInfoSpec Optional. Array of extra information that should be passed to the listener function. + */ + addListener(callback: (details: OnSendHeadersDetailsType) => void, filter: RequestFilter, extraInfoSpec?: OnSendHeadersOptions[]): void; + } + /** + * Fired when HTTP response headers of a request have been received. + */ + interface OnHeadersReceivedEvent extends Events.Event<(details: OnHeadersReceivedDetailsType) => BlockingResponseOrPromiseOrVoid> { + /** + * Registers an event listener <em>callback</em> to an event. + * + * @param callback Called when an event occurs. The parameters of this function depend on the type of event. + * @param filter A set of filters that restricts the events that will be sent to this listener. + * @param extraInfoSpec Optional. Array of extra information that should be passed to the listener function. + */ + addListener(callback: (details: OnHeadersReceivedDetailsType) => BlockingResponseOrPromiseOrVoid, filter: RequestFilter, extraInfoSpec?: OnHeadersReceivedOptions[]): void; + } + /** + * Fired when an authentication failure is received. The listener has three options: it can provide authentication + * credentials, it can cancel the request and display the error page, or it can take no action on the challenge. + * If bad user credentials are provided, this may be called multiple times for the same request. + */ + interface OnAuthRequiredEvent extends Events.Event<(details: OnAuthRequiredDetailsType) => BlockingResponseOrPromiseOrVoid> { + /** + * Registers an event listener <em>callback</em> to an event. + * + * @param callback Called when an event occurs. The parameters of this function depend on the type of event. + * @param filter A set of filters that restricts the events that will be sent to this listener. + * @param extraInfoSpec Optional. Array of extra information that should be passed to the listener function. + */ + addListener(callback: (details: OnAuthRequiredDetailsType) => BlockingResponseOrPromiseOrVoid, filter: RequestFilter, extraInfoSpec?: OnAuthRequiredOptions[]): void; + } + /** + * Fired when the first byte of the response body is received. For HTTP requests, this means that the status line and + * response headers are available. + */ + interface OnResponseStartedEvent extends Events.Event<(details: OnResponseStartedDetailsType) => void> { + /** + * Registers an event listener <em>callback</em> to an event. + * + * @param callback Called when an event occurs. The parameters of this function depend on the type of event. + * @param filter A set of filters that restricts the events that will be sent to this listener. + * @param extraInfoSpec Optional. Array of extra information that should be passed to the listener function. + */ + addListener(callback: (details: OnResponseStartedDetailsType) => void, filter: RequestFilter, extraInfoSpec?: OnResponseStartedOptions[]): void; + } + /** + * Fired when a server-initiated redirect is about to occur. + */ + interface OnBeforeRedirectEvent extends Events.Event<(details: OnBeforeRedirectDetailsType) => void> { + /** + * Registers an event listener <em>callback</em> to an event. + * + * @param callback Called when an event occurs. The parameters of this function depend on the type of event. + * @param filter A set of filters that restricts the events that will be sent to this listener. + * @param extraInfoSpec Optional. Array of extra information that should be passed to the listener function. + */ + addListener(callback: (details: OnBeforeRedirectDetailsType) => void, filter: RequestFilter, extraInfoSpec?: OnBeforeRedirectOptions[]): void; + } + /** + * Fired when a request is completed. + */ + interface OnCompletedEvent extends Events.Event<(details: OnCompletedDetailsType) => void> { + /** + * Registers an event listener <em>callback</em> to an event. + * + * @param callback Called when an event occurs. The parameters of this function depend on the type of event. + * @param filter A set of filters that restricts the events that will be sent to this listener. + * @param extraInfoSpec Optional. Array of extra information that should be passed to the listener function. + */ + addListener(callback: (details: OnCompletedDetailsType) => void, filter: RequestFilter, extraInfoSpec?: OnCompletedOptions[]): void; + } + /** + * Fired when an error occurs. + */ + interface OnErrorOccurredEvent extends Events.Event<(details: OnErrorOccurredDetailsType) => void> { + /** + * Registers an event listener <em>callback</em> to an event. + * + * @param callback Called when an event occurs. The parameters of this function depend on the type of event. + * @param filter A set of filters that restricts the events that will be sent to this listener. + * @param extraInfoSpec Optional. Array of extra information that should be passed to the listener function. + */ + addListener(callback: (details: OnErrorOccurredDetailsType) => void, filter: RequestFilter, extraInfoSpec?: OnErrorOccurredOptions[]): void; + } + interface Static { + /** + * Needs to be called when the behavior of the webRequest handlers has changed to prevent incorrect handling due to caching. + * This function call is expensive. Don't call it often. + */ + handlerBehaviorChanged(): Promise<void>; + /** + * ... + */ + filterResponseData(requestId: string): StreamFilter; + /** + * Retrieves the security information for the request. Returns a promise that will resolve to a SecurityInfo object. + * + * @param options Optional. + */ + getSecurityInfo(requestId: string, options?: GetSecurityInfoOptionsType): Promise<SecurityInfo>; + /** + * Fired when a request is about to occur. + */ + onBeforeRequest: OnBeforeRequestEvent; + /** + * Fired before sending an HTTP request, once the request headers are available. This may occur after a TCP connection is + * made to the server, but before any HTTP data is sent. + */ + onBeforeSendHeaders: OnBeforeSendHeadersEvent; + /** + * Fired just before a request is going to be sent to the server (modifications of previous onBeforeSendHeaders callbacks + * are visible by the time onSendHeaders is fired). + */ + onSendHeaders: OnSendHeadersEvent; + /** + * Fired when HTTP response headers of a request have been received. + */ + onHeadersReceived: OnHeadersReceivedEvent; + /** + * Fired when an authentication failure is received. The listener has three options: it can provide authentication + * credentials, it can cancel the request and display the error page, or it can take no action on the challenge. + * If bad user credentials are provided, this may be called multiple times for the same request. + */ + onAuthRequired: OnAuthRequiredEvent; + /** + * Fired when the first byte of the response body is received. For HTTP requests, this means that the status line and + * response headers are available. + */ + onResponseStarted: OnResponseStartedEvent; + /** + * Fired when a server-initiated redirect is about to occur. + */ + onBeforeRedirect: OnBeforeRedirectEvent; + /** + * Fired when a request is completed. + */ + onCompleted: OnCompletedEvent; + /** + * Fired when an error occurs. + */ + onErrorOccurred: OnErrorOccurredEvent; + /** + * The maximum number of times that <code>handlerBehaviorChanged</code> can be called per 10 minute sustained interval. + * <code>handlerBehaviorChanged</code> is an expensive function call that shouldn't be called often. + */ + MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES: 20; + } + } + /** + * Namespace: browser.windows + */ + namespace Windows { + /** + * The type of browser window this is. Under some circumstances a Window may not be assigned type property, + * for example when querying closed windows from the $(ref:sessions) API. + */ + type WindowType = "normal" | "popup" | "panel" | "app" | "devtools"; + /** + * The state of this browser window. Under some circumstances a Window may not be assigned state property, + * for example when querying closed windows from the $(ref:sessions) API. + */ + type WindowState = "normal" | "minimized" | "maximized" | "fullscreen" | "docked"; + interface Window { + /** + * The ID of the window. Window IDs are unique within a browser session. Under some circumstances a Window may not be + * assigned an ID, for example when querying windows using the $(ref:sessions) API, in which case a session ID may be + * present. + * Optional. + */ + id?: number; + /** + * Whether the window is currently the focused window. + */ + focused: boolean; + /** + * The offset of the window from the top edge of the screen in pixels. Under some circumstances a Window may not be + * assigned top property, for example when querying closed windows from the $(ref:sessions) API. + * Optional. + */ + top?: number; + /** + * The offset of the window from the left edge of the screen in pixels. Under some circumstances a Window may not be + * assigned left property, for example when querying closed windows from the $(ref:sessions) API. + * Optional. + */ + left?: number; + /** + * The width of the window, including the frame, in pixels. Under some circumstances a Window may not be assigned width + * property, for example when querying closed windows from the $(ref:sessions) API. + * Optional. + */ + width?: number; + /** + * The height of the window, including the frame, in pixels. Under some circumstances a Window may not be assigned height + * property, for example when querying closed windows from the $(ref:sessions) API. + * Optional. + */ + height?: number; + /** + * Array of $(ref:tabs.Tab) objects representing the current tabs in the window. + * Optional. + */ + tabs?: Browser.Tabs.Tab[]; + /** + * Whether the window is incognito. + */ + incognito: boolean; + /** + * The type of browser window this is. + * Optional. + */ + type?: WindowType; + /** + * The state of this browser window. + * Optional. + */ + state?: WindowState; + /** + * Whether the window is set to be always on top. + */ + alwaysOnTop: boolean; + /** + * The session ID used to uniquely identify a Window obtained from the $(ref:sessions) API. + * Optional. + */ + sessionId?: string; + /** + * The title of the window. Read-only. + * Optional. + */ + title?: string; + } + /** + * Specifies what type of browser window to create. The 'panel' and 'detached_panel' types create a popup unless the + * '--enable-panels' flag is set. + */ + type CreateType = "normal" | "popup" | "panel" | "detached_panel"; + /** + * Specifies whether the $(ref:windows.Window) returned should contain a list of the $(ref:tabs.Tab) objects. + */ + interface GetInfo { + /** + * If true, the $(ref:windows.Window) returned will have a <var>tabs</var> property that contains a list of the $(ref:tabs. + * Tab) objects. The <code>Tab</code> objects only contain the <code>url</code>, <code>title</code> and <code> + * favIconUrl</code> properties if the extension's manifest file includes the <code>"tabs"</code> permission. + * Optional. + */ + populate?: boolean; + } + /** + * Specifies properties used to filter the $(ref:windows.Window) returned and to determine whether they should contain a + * list of the $(ref:tabs.Tab) objects. + */ + interface GetAllGetInfoType extends GetInfo { + /** + * If set, the $(ref:windows.Window) returned will be filtered based on its type. If unset the default filter is set to + * <code>['app', 'normal', 'panel', 'popup']</code>, with <code>'app'</code> and <code>'panel'</code> + * window types limited to the extension's own windows. + * Optional. + */ + windowTypes?: WindowType[]; + } + interface CreateCreateDataType { + /** + * A URL or array of URLs to open as tabs in the window. Fully-qualified URLs must include a scheme (i.e. 'http://www. + * google.com', not 'www.google.com'). Relative URLs will be relative to the current page within the extension. + * Defaults to the New Tab Page. + * Optional. + */ + url?: string | string[]; + /** + * The id of the tab for which you want to adopt to the new window. + * Optional. + */ + tabId?: number; + /** + * The number of pixels to position the new window from the left edge of the screen. If not specified, + * the new window is offset naturally from the last focused window. This value is ignored for panels. + * Optional. + */ + left?: number; + /** + * The number of pixels to position the new window from the top edge of the screen. If not specified, + * the new window is offset naturally from the last focused window. This value is ignored for panels. + * Optional. + */ + top?: number; + /** + * The width in pixels of the new window, including the frame. If not specified defaults to a natural width. + * Optional. + */ + width?: number; + /** + * The height in pixels of the new window, including the frame. If not specified defaults to a natural height. + * Optional. + */ + height?: number; + /** + * If true, the new window will be focused. If false, the new window will be opened in the background and the currently + * focused window will stay focused. Defaults to true. + * Optional. + */ + focused?: boolean; + /** + * Whether the new window should be an incognito window. + * Optional. + */ + incognito?: boolean; + /** + * Specifies what type of browser window to create. The 'panel' and 'detached_panel' types create a popup unless the + * '--enable-panels' flag is set. + * Optional. + */ + type?: CreateType; + /** + * The initial state of the window. The 'minimized', 'maximized' and 'fullscreen' states cannot be combined with 'left', + * 'top', 'width' or 'height'. + * Optional. + */ + state?: WindowState; + /** + * Allow scripts to close the window. + * Optional. + */ + allowScriptsToClose?: boolean; + /** + * The CookieStoreId to use for all tabs that were created when the window is opened. + * Optional. + */ + cookieStoreId?: string; + /** + * A string to add to the beginning of the window title. + * Optional. + */ + titlePreface?: string; + } + interface UpdateUpdateInfoType { + /** + * The offset from the left edge of the screen to move the window to in pixels. This value is ignored for panels. + * Optional. + */ + left?: number; + /** + * The offset from the top edge of the screen to move the window to in pixels. This value is ignored for panels. + * Optional. + */ + top?: number; + /** + * The width to resize the window to in pixels. This value is ignored for panels. + * Optional. + */ + width?: number; + /** + * The height to resize the window to in pixels. This value is ignored for panels. + * Optional. + */ + height?: number; + /** + * If true, brings the window to the front. If false, brings the next window in the z-order to the front. + * Optional. + */ + focused?: boolean; + /** + * If true, causes the window to be displayed in a manner that draws the user's attention to the window, + * without changing the focused window. The effect lasts until the user changes focus to the window. + * This option has no effect if the window already has focus. Set to false to cancel a previous draw attention request. + * Optional. + */ + drawAttention?: boolean; + /** + * The new state of the window. The 'minimized', 'maximized' and 'fullscreen' states cannot be combined with 'left', 'top', + * 'width' or 'height'. + * Optional. + */ + state?: WindowState; + /** + * A string to add to the beginning of the window title. + * Optional. + */ + titlePreface?: string; + } + interface Static { + /** + * Gets details about a window. + * + * @param getInfo Optional. + */ + get(windowId: number, getInfo?: GetInfo): Promise<Window>; + /** + * Gets the $(topic:current-window)[current window]. + * + * @param getInfo Optional. + */ + getCurrent(getInfo?: GetInfo): Promise<Window>; + /** + * Gets the window that was most recently focused — typically the window 'on top'. + * + * @param getInfo Optional. + */ + getLastFocused(getInfo?: GetInfo): Promise<Window>; + /** + * Gets all windows. + * + * @param getInfo Optional. Specifies properties used to filter the $(ref:windows.Window) + * returned and to determine whether they should contain a list of the $(ref:tabs.Tab) objects. + */ + getAll(getInfo?: GetAllGetInfoType): Promise<Window[]>; + /** + * Creates (opens) a new browser with any optional sizing, position or default URL provided. + * + * @param createData Optional. + */ + create(createData?: CreateCreateDataType): Promise<Window>; + /** + * Updates the properties of a window. Specify only the properties that you want to change; unspecified properties will be + * left unchanged. + */ + update(windowId: number, updateInfo: UpdateUpdateInfoType): Promise<Window>; + /** + * Removes (closes) a window, and all the tabs inside it. + */ + remove(windowId: number): Promise<void>; + /** + * Fired when a window is created. + * + * @param window Details of the window that was created. + */ + onCreated: Events.Event<(window: Window) => void>; + /** + * Fired when a window is removed (closed). + * + * @param windowId ID of the removed window. + */ + onRemoved: Events.Event<(windowId: number) => void>; + /** + * Fired when the currently focused window changes. Will be $(ref:windows.WINDOW_ID_NONE) + * if all browser windows have lost focus. Note: On some Linux window managers, WINDOW_ID_NONE will always be sent + * immediately preceding a switch from one browser window to another. + * + * @param windowId ID of the newly focused window. + */ + onFocusChanged: Events.Event<(windowId: number) => void>; + /** + * The windowId value that represents the absence of a browser window. + */ + WINDOW_ID_NONE: -1; + /** + * The windowId value that represents the $(topic:current-window)[current window]. + */ + WINDOW_ID_CURRENT: -2; + } + } + namespace BrowserSettings { + namespace ColorManagement { + interface Static { + /** + * This setting controls the mode used for color management and must be a string from $(ref:browserSettings. + * ColorManagementMode) + */ + mode: Browser.Types.Setting; + /** + * This boolean setting controls whether or not native sRGB color management is used. + */ + useNativeSRGB: Browser.Types.Setting; + /** + * This boolean setting controls whether or not the WebRender compositor is used. + */ + useWebRenderCompositor: Browser.Types.Setting; + } + } + } + namespace Devtools { + namespace InspectedWindow { + /** + * A resource within the inspected page, such as a document, a script, or an image. + */ + interface Resource { + /** + * The URL of the resource. + */ + url: string; + } + /** + * The options parameter can contain one or more options. + */ + interface EvalOptionsType { + [s: string]: unknown; + } + /** + * An object providing details if an exception occurred while evaluating the expression. + */ + interface EvalCallbackExceptionInfoType { + /** + * Set if the error occurred on the DevTools side before the expression is evaluated. + */ + isError: boolean; + /** + * Set if the error occurred on the DevTools side before the expression is evaluated. + */ + code: string; + /** + * Set if the error occurred on the DevTools side before the expression is evaluated. + */ + description: string; + /** + * Set if the error occurred on the DevTools side before the expression is evaluated, + * contains the array of the values that may be substituted into the description string to provide more information about + * the cause of the error. + */ + details: unknown[]; + /** + * Set if the evaluated code produces an unhandled exception. + */ + isException: boolean; + /** + * Set if the evaluated code produces an unhandled exception. + */ + value: string; + } + interface ReloadReloadOptionsType { + /** + * When true, the loader will bypass the cache for all inspected page resources loaded before the <code>load</code> + * event is fired. The effect is similar to pressing Ctrl+Shift+R in the inspected window or within the Developer Tools + * window. + * Optional. + */ + ignoreCache?: boolean; + /** + * If specified, the string will override the value of the <code>User-Agent</code> HTTP header that's sent while loading + * the resources of the inspected page. The string will also override the value of the <code>navigator.userAgent</code> + * property that's returned to any scripts that are running within the inspected page. + * Optional. + */ + userAgent?: string; + /** + * If specified, the script will be injected into every frame of the inspected page immediately upon load, + * before any of the frame's scripts. The script will not be injected after subsequent reloads—for example, + * if the user presses Ctrl+R. + * Optional. + */ + injectedScript?: string; + } + interface Static { + /** + * Evaluates a JavaScript expression in the context of the main frame of the inspected page. + * The expression must evaluate to a JSON-compliant object, otherwise an exception is thrown. + * The eval function can report either a DevTools-side error or a JavaScript exception that occurs during evaluation. + * In either case, the <code>result</code> parameter of the callback is <code>undefined</code>. + * In the case of a DevTools-side error, the <code>isException</code> parameter is non-null and has <code>isError</code> + * set to true and <code>code</code> set to an error code. In the case of a JavaScript error, <code>isException</code> + * is set to true and <code>value</code> is set to the string value of thrown object. + * + * @param expression An expression to evaluate. + * @param options Optional. The options parameter can contain one or more options. + * @returns A function called when evaluation completes. + */ + eval(expression: string, options?: EvalOptionsType): Promise<[ + unknown, + EvalCallbackExceptionInfoType + ]>; + /** + * Reloads the inspected page. + * + * @param reloadOptions Optional. + */ + reload(reloadOptions?: ReloadReloadOptionsType): void; + /** + * The ID of the tab being inspected. This ID may be used with chrome.tabs.* API. + */ + tabId: number; + } + } + } + namespace Devtools { + namespace Network { + /** + * Represents a network request for a document resource (script, image and so on). See HAR Specification for reference. + */ + interface Request { + /** + * Returns content of the response body. + * + * @returns A function that receives the response body when the request completes. + */ + getContent(): Promise<[ + string, + string + ]>; + } + /** + * A HAR log. See HAR specification for details. + */ + interface GetHARCallbackHarLogType { + [s: string]: unknown; + } + interface Static { + /** + * Returns HAR log that contains all known network requests. + * + * @returns A function that receives the HAR log when the request completes. + */ + getHAR(): Promise<GetHARCallbackHarLogType>; + /** + * Fired when a network request is finished and all request data are available. + * + * @param request Description of a network request in the form of a HAR entry. See HAR specification for details. + */ + onRequestFinished: Events.Event<(request: Request) => void>; + /** + * Fired when the inspected window navigates to a new page. + * + * @param url URL of the new page. + */ + onNavigated: Events.Event<(url: string) => void>; + } + } + } + namespace Devtools { + namespace Panels { + /** + * Represents the Elements panel. + */ + interface ElementsPanel { + /** + * Creates a pane within panel's sidebar. + * + * @param title Text that is displayed in sidebar caption. + * @returns A callback invoked when the sidebar is created. + */ + createSidebarPane(title: string): Promise<ExtensionSidebarPane>; + /** + * Fired when an object is selected in the panel. + */ + onSelectionChanged: Events.Event<() => void>; + } + /** + * Represents the Sources panel. + */ + interface SourcesPanel { + [s: string]: unknown; + } + /** + * Represents a panel created by extension. + */ + interface ExtensionPanel { + /** + * Fired when the user switches to the panel. + * + * @param window The JavaScript <code>window</code> object of panel's page. + */ + onShown: Events.Event<(window: Window) => void>; + /** + * Fired when the user switches away from the panel. + */ + onHidden: Events.Event<() => void>; + } + /** + * A sidebar created by the extension. + */ + interface ExtensionSidebarPane { + /** + * Sets an expression that is evaluated within the inspected page. The result is displayed in the sidebar pane. + * + * @param expression An expression to be evaluated in context of the inspected page. JavaScript objects and DOM nodes are + * displayed in an expandable tree similar to the console/watch. + * @param rootTitle Optional. An optional title for the root of the expression tree. + * @returns A callback invoked after the sidebar pane is updated with the expression evaluation results. + */ + setExpression(expression: string, rootTitle?: string): Promise<void>; + /** + * Sets a JSON-compliant object to be displayed in the sidebar pane. + * + * @param jsonObject An object to be displayed in context of the inspected page. Evaluated in the context of the caller + * (API client). + * @param rootTitle Optional. An optional title for the root of the expression tree. + * @returns A callback invoked after the sidebar is updated with the object. + */ + setObject(jsonObject: string | unknown[] | Record<string, unknown>, rootTitle?: string): Promise<void>; + /** + * Sets an HTML page to be displayed in the sidebar pane. + * + * @param path Relative path of an extension page to display within the sidebar. + */ + setPage(path: Browser.Manifest.ExtensionURL): Promise<void>; + /** + * Fired when the sidebar pane becomes visible as a result of user switching to the panel that hosts it. + * + * @param window The JavaScript <code>window</code> object of the sidebar page, if one was set with the <code>setPage() + * </code> method. + */ + onShown: Events.Event<(window: Window) => void>; + /** + * Fired when the sidebar pane becomes hidden as a result of the user switching away from the panel that hosts the sidebar + * pane. + */ + onHidden: Events.Event<() => void>; + } + /** + * A button created by the extension. + */ + interface Button { + [s: string]: unknown; + } + interface Static { + /** + * Creates an extension panel. + * + * @param title Title that is displayed next to the extension icon in the Developer Tools toolbar. + * @param iconPath Path of the panel's icon relative to the extension directory, or an empty string to use the default + * extension icon as the panel icon. + * @param pagePath Path of the panel's HTML page relative to the extension directory. + * @returns A function that is called when the panel is created. + */ + create(title: string, iconPath: "" | Browser.Manifest.ExtensionURL, pagePath: Browser.Manifest.ExtensionURL): Promise<ExtensionPanel>; + /** + * Fired when the devtools theme changes. + * + * @param themeName The name of the current devtools theme. + */ + onThemeChanged: Events.Event<(themeName: string) => void>; + /** + * Elements panel. + */ + elements: ElementsPanel; + /** + * Sources panel. + */ + sources: SourcesPanel; + /** + * The name of the current devtools theme. + */ + themeName: string; + } + } + } + namespace Privacy { + namespace Network { + /** + * The IP handling policy of WebRTC. + */ + type IPHandlingPolicy = "default" | "default_public_and_private_interfaces" | "default_public_interface_only" | "disable_non_proxied_udp" | "proxy_only"; + /** + * An object which describes TLS minimum and maximum versions. + */ + interface tlsVersionRestrictionConfig { + /** + * The minimum TLS version supported. + * Optional. + */ + minimum?: TlsVersionRestrictionConfigMinimumEnum; + /** + * The maximum TLS version supported. + * Optional. + */ + maximum?: TlsVersionRestrictionConfigMaximumEnum; + } + /** + * The mode for https-only mode. + */ + type HTTPSOnlyModeOption = "always" | "private_browsing" | "never"; + /** + * The minimum TLS version supported. + */ + type TlsVersionRestrictionConfigMinimumEnum = "TLSv1" | "TLSv1.1" | "TLSv1.2" | "TLSv1.3" | "unknown"; + /** + * The maximum TLS version supported. + */ + type TlsVersionRestrictionConfigMaximumEnum = "TLSv1" | "TLSv1.1" | "TLSv1.2" | "TLSv1.3" | "unknown"; + interface Static { + /** + * If enabled, the browser attempts to speed up your web browsing experience by pre-resolving DNS entries, + * prerendering sites (<code><link rel='prefetch' ...></code>), and preemptively opening TCP and SSL connections to + * servers. This preference's value is a boolean, defaulting to <code>true</code>. + */ + networkPredictionEnabled: Browser.Types.Setting; + /** + * Allow users to enable and disable RTCPeerConnections (aka WebRTC). + */ + peerConnectionEnabled: Browser.Types.Setting; + /** + * Allow users to specify the media performance/privacy tradeoffs which impacts how WebRTC traffic will be routed and how + * much local address information is exposed. This preference's value is of type IPHandlingPolicy, defaulting to <code> + * default</code>. + */ + webRTCIPHandlingPolicy: Browser.Types.Setting; + /** + * This property controls the minimum and maximum TLS versions. This setting's value is an object of + * $(ref:tlsVersionRestrictionConfig). + */ + tlsVersionRestriction: Browser.Types.Setting; + /** + * Allow users to query the mode for 'HTTPS-Only Mode'. This setting's value is of type HTTPSOnlyModeOption, + * defaulting to <code>never</code>. + */ + httpsOnlyMode: Browser.Types.Setting; + /** + * Allow users to query the status of 'Global Privacy Control'. This setting's value is of type boolean, + * defaulting to <code>false</code>. + */ + globalPrivacyControl: Browser.Types.Setting; + } + } + } + namespace Privacy { + namespace Services { + interface Static { + /** + * If enabled, the password manager will ask if you want to save passwords. This preference's value is a boolean, + * defaulting to <code>true</code>. + */ + passwordSavingEnabled: Browser.Types.Setting; + } + } + } + namespace Privacy { + namespace Websites { + /** + * The mode for tracking protection. + */ + type TrackingProtectionModeOption = "always" | "never" | "private_browsing"; + /** + * The settings for cookies. + */ + interface CookieConfig { + /** + * The type of cookies to allow. + * Optional. + */ + behavior?: CookieConfigBehaviorEnum; + } + /** + * The type of cookies to allow. + */ + type CookieConfigBehaviorEnum = "allow_all" | "reject_all" | "reject_third_party" | "allow_visited" | "reject_trackers" | "reject_trackers_and_partition_foreign"; + interface Static { + /** + * If enabled, the browser sends auditing pings when requested by a website (<code><a ping></code>). + * The value of this preference is of type boolean, and the default value is <code>true</code>. + */ + hyperlinkAuditingEnabled: Browser.Types.Setting; + /** + * If enabled, the browser sends <code>referer</code> headers with your requests. Yes, + * the name of this preference doesn't match the misspelled header. No, we're not going to change it. + * The value of this preference is of type boolean, and the default value is <code>true</code>. + */ + referrersEnabled: Browser.Types.Setting; + /** + * If enabled, the browser attempts to appear similar to other users by reporting generic information to websites. + * This can prevent websites from uniquely identifying users. Examples of data that is spoofed include number of CPU cores, + * precision of JavaScript timers, the local timezone, and disabling features such as GamePad support, + * and the WebSpeech and Navigator APIs. The value of this preference is of type boolean, and the default value is <code> + * false</code>. + */ + resistFingerprinting: Browser.Types.Setting; + /** + * If enabled, the browser will associate all data (including cookies, HSTS data, cached images, and more) + * for any third party domains with the domain in the address bar. This prevents third party trackers from using directly + * stored information to identify you across different websites, but may break websites where you login with a third party + * account (such as a Facebook or Google login.) The value of this preference is of type boolean, + * and the default value is <code>false</code>. + */ + firstPartyIsolate: Browser.Types.Setting; + /** + * Allow users to specify the mode for tracking protection. This setting's value is of type TrackingProtectionModeOption, + * defaulting to <code>private_browsing_only</code>. + */ + trackingProtectionMode: Browser.Types.Setting; + /** + * Allow users to specify the default settings for allowing cookies, as well as whether all cookies should be created as + * non-persistent cookies. This setting's value is of type CookieConfig. + */ + cookieConfig: Browser.Types.Setting; + } + } + } + namespace Trial { + namespace Ml { + interface CreateEngineRequest { + [s: string]: unknown; + } + interface RunEngineRequest { + [s: string]: unknown; + } + /** + * Object containing the data, see https://firefox-source-docs.mozilla.org/toolkit/components/ml/notifications.html + */ + interface OnProgressProgressDataType { + [s: string]: unknown; + } + interface Static { + /** + * Prepare the inference engine + */ + createEngine(CreateEngineRequest: CreateEngineRequest): void; + /** + * Call the inference engine + */ + runEngine(RunEngineRequest: RunEngineRequest): void; + /** + * Delete the models the extension downloaded. + */ + deleteCachedModels(): void; + /** + * Events from the inference engine. + * + * @param progressData Object containing the data, see https://firefox-source-docs.mozilla. + * org/toolkit/components/ml/notifications.html + */ + onProgress: Events.Event<(progressData: OnProgressProgressDataType) => void>; + } + } + } + interface Browser { + /** + * Monitor extension activity + * + * Permissions: "activityLog" + */ + activityLog: ActivityLog.Static; + /** + * Permissions: "alarms" + */ + alarms: Alarms.Static; + /** + * Use the <code>browser.bookmarks</code> API to create, organize, and otherwise manipulate bookmarks. + * Also see $(topic:override)[Override Pages], which you can use to create a custom Bookmark Manager page. + * + * Permissions: "bookmarks" + */ + bookmarks: Bookmarks.Static; + /** + * Use browser actions to put icons in the main browser toolbar, to the right of the address bar. In addition to its icon, + * a browser action can also have a tooltip, a badge, and a popup. + * + * Permissions: "manifest:action", "manifest:browser_action" + */ + action: Action.Static; + /** + * Permissions: "manifest:action", "manifest:browser_action" + */ + browserAction: BrowserAction.Static; + /** + * Use the <code>browser.browserSettings</code> API to control global settings of the browser. + * + * Permissions: "browserSettings" + */ + browserSettings: BrowserSettings.Static; + /** + * Use the <code>chrome.browsingData</code> API to remove browsing data from a user's local profile. + * + * Permissions: "browsingData" + */ + browsingData: BrowsingData.Static; + /** + * This API provides the ability detect the captive portal state of the users connection. + * + * Permissions: "captivePortal" + */ + captivePortal: CaptivePortal.Static; + /** + * Offers the ability to write to the clipboard. Reading is not supported because the clipboard can already be read through + * the standard web platform APIs. + * + * Permissions: "clipboardWrite" + */ + clipboard: Clipboard.Static; + /** + * Use the commands API to add keyboard shortcuts that trigger actions in your extension, for example, + * an action to open the browser action or send a command to the xtension. + * + * Permissions: "manifest:commands" + */ + commands: Commands.Static; + contentScripts: ContentScripts.Static; + /** + * Use the <code>browser.contextualIdentities</code> API to query and modify contextual identity, also called as containers. + * + * Permissions: "contextualIdentities" + */ + contextualIdentities: ContextualIdentities.Static; + /** + * Use the <code>browser.cookies</code> API to query and modify cookies, and to be notified when they change. + * + * Permissions: "cookies" + */ + cookies: Cookies.Static; + /** + * Use the <code>chrome.declarativeContent</code> API to take actions depending on the content of a page, + * without requiring permission to read the page's content. + */ + declarativeContent: DeclarativeContent.Static; + /** + * Use the declarativeNetRequest API to block or modify network requests by specifying declarative rules. + * + * Permissions: "declarativeNetRequest", "declarativeNetRequestWithHostAccess" + */ + declarativeNetRequest: DeclarativeNetRequest.Static; + /** + * Permissions: "manifest:devtools_page" + */ + devtools: Devtools.Static; + /** + * Asynchronous DNS API + * + * Permissions: "dns" + */ + dns: Dns.Static; + /** + * Permissions: "downloads" + */ + downloads: Downloads.Static; + /** + * The <code>chrome.events</code> namespace contains common types used by APIs dispatching events to notify you when + * something interesting happens. + */ + events: Events.Static; + experiments: Experiments.Static; + /** + * The <code>browser.extensionTypes</code> API contains type declarations for WebExtensions. + */ + extensionTypes: ExtensionTypes.Static; + /** + * The <code>browser.extension</code> API has utilities that can be used by any extension page. + * It includes support for exchanging messages between an extension and its content scripts or between extensions, + * as described in detail in $(topic:messaging)[Message Passing]. + */ + extension: Extension.Static; + /** + * Use the <code>browser.find</code> API to interact with the browser's <code>Find</code> interface. + * + * Permissions: "find" + */ + find: Find.Static; + /** + * Exposes the browser's profiler. + * + * Permissions: "geckoProfiler" + */ + geckoProfiler: GeckoProfiler.Static; + /** + * Use the <code>browser.history</code> API to interact with the browser's record of visited pages. You can add, remove, + * and query for URLs in the browser's history. To override the history page with your own version, see $(topic:override) + * [Override Pages]. + * + * Permissions: "history" + */ + history: History.Static; + /** + * Use the <code>browser.i18n</code> infrastructure to implement internationalization across your whole app or extension. + */ + i18n: I18n.Static; + /** + * Use the chrome.identity API to get OAuth2 access tokens. + * + * Permissions: "identity" + */ + identity: Identity.Static; + /** + * Use the <code>browser.idle</code> API to detect when the machine's idle state changes. + * + * Permissions: "idle" + */ + idle: Idle.Static; + /** + * The <code>browser.management</code> API provides ways to manage the list of extensions that are installed and running. + */ + management: Management.Static; + /** + * Permissions: - + */ + manifest: Manifest.Static; + /** + * Use the browser.contextMenus API to add items to the browser's context menu. You can choose what types of objects your + * context menu additions apply to, such as images, hyperlinks, and pages. + * + * Permissions: "contextMenus" + */ + contextMenus: ContextMenus.Static; + /** + * Use the browser.menus API to add items to the browser's menus. You can choose what types of objects your context menu + * additions apply to, such as images, hyperlinks, and pages. + * + * Permissions: "menus" + */ + menus: Menus.Static; + /** + * This API provides the ability to determine the status of and detect changes in the network connection. + * This API can only be used in privileged extensions. + * + * Permissions: "networkStatus" + */ + networkStatus: NetworkStatus.Static; + /** + * Normandy Study API + * + * Permissions: "normandyAddonStudy" + */ + normandyAddonStudy: NormandyAddonStudy.Static; + /** + * Permissions: "notifications" + */ + notifications: Notifications.Static; + /** + * The omnibox API allows you to register a keyword with Firefox's address bar. + * + * Permissions: "manifest:omnibox" + */ + omnibox: Omnibox.Static; + /** + * Use the <code>browser.pageAction</code> API to put icons inside the address bar. Page actions represent actions that can + * be taken on the current page, but that aren't applicable to all pages. + * + * Permissions: "manifest:page_action" + */ + pageAction: PageAction.Static; + permissions: Permissions.Static; + /** + * PKCS#11 module management API + * + * Permissions: "pkcs11" + */ + pkcs11: Pkcs11.Static; + /** + * Permissions: "privacy" + */ + privacy: Privacy.Static; + /** + * Provides access to global proxy settings for Firefox and proxy event listeners to handle dynamic proxy implementations. + * + * Permissions: "proxy" + */ + proxy: Proxy.Static; + /** + * Use the <code>browser.runtime</code> API to retrieve the background page, return details about the manifest, + * and listen for and respond to events in the app or extension lifecycle. You can also use this API to convert the + * relative path of URLs to fully-qualified URLs. + */ + runtime: Runtime.Static; + /** + * Use the scripting API to execute script in different contexts. + * + * Permissions: "scripting" + */ + scripting: Scripting.Static; + /** + * Use browser.search to interact with search engines. + * + * Permissions: "search" + */ + search: Search.Static; + /** + * Use the <code>chrome.sessions</code> API to query and restore tabs and windows from a browsing session. + * + * Permissions: "sessions" + */ + sessions: Sessions.Static; + /** + * Use sidebar actions to add a sidebar to Firefox. + * + * Permissions: "manifest:sidebar_action" + */ + sidebarAction: SidebarAction.Static; + /** + * Use the <code>browser.storage</code> API to store, retrieve, and track changes to user data. + * + * Permissions: "storage" + */ + storage: Storage.Static; + /** + * Use the browser.tabGroups API to interact with the browser's tab grouping system. You can use this API to modify, + * and rearrange tab groups. + * + * Permissions: "tabGroups" + */ + tabGroups: TabGroups.Static; + /** + * Use the <code>browser.tabs</code> API to interact with the browser's tab system. You can use this API to create, modify, + * and rearrange tabs in the browser. + */ + tabs: Tabs.Static; + /** + * The theme API allows customizing of visual elements of the browser. + */ + theme: Theme.Static; + /** + * Use the chrome.topSites API to access the top sites that are displayed on the new tab page. + * + * Permissions: "topSites" + */ + topSites: TopSites.Static; + /** + * Permissions: "trialML" + */ + trial: Trial.Static; + /** + * Contains types used by other schemas. + */ + types: Types.Static; + /** + * Permissions: "manifest:user_scripts", "userScripts" + */ + userScripts: UserScripts.Static; + /** + * Use the <code>browser.webNavigation</code> API to receive notifications about the status of navigation requests + * in-flight. + * + * Permissions: "webNavigation" + */ + webNavigation: WebNavigation.Static; + /** + * Use the <code>browser.webRequest</code> API to observe and analyze traffic and to intercept, block, + * or modify requests in-flight. + * + * Permissions: "webRequest" + */ + webRequest: WebRequest.Static; + /** + * Use the <code>browser.windows</code> API to interact with browser windows. You can use this API to create, modify, + * and rearrange windows in the browser. + */ + windows: Windows.Static; + } + } +} +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +declare global { + interface GlideModes { + hint: "hint"; + } +} +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +declare global { + interface ExcmdRegistry { + jumplist_back: {}; + jumplist_forward: {}; + } +} +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +declare global { + interface ExcmdRegistry { + whichkey: {}; + } +} + +export {}; diff --git a/glide/glide.ts b/config/glide/glide.ts index 502f088..502f088 100644 --- a/glide/glide.ts +++ b/config/glide/glide.ts diff --git a/config/glirc/config b/config/glirc/config new file mode 100644 index 0000000..80d2e5e --- /dev/null +++ b/config/glirc/config @@ -0,0 +1,18 @@ + +defaults: + nick: "tccq" + username: "tccq" + tls: yes + +servers: + * name: "libera" + hostname: "irc.libera.chat" + sasl: + username: "tccq" + password: "sNH6Gr@X4(H(N,[/{|`,n1W9g" + +nick-padding: + side: right + width: 13 + +url-opener: "xdg-open" diff --git a/qutebrowser/autoconfig.yml b/config/qutebrowser/autoconfig.yml index 071b9d5..071b9d5 100644 --- a/qutebrowser/autoconfig.yml +++ b/config/qutebrowser/autoconfig.yml diff --git a/qutebrowser/bookmarks/urls b/config/qutebrowser/bookmarks/urls index e69de29..e69de29 100644 --- a/qutebrowser/bookmarks/urls +++ b/config/qutebrowser/bookmarks/urls diff --git a/qutebrowser/quickmarks b/config/qutebrowser/quickmarks index e69de29..e69de29 100644 --- a/qutebrowser/quickmarks +++ b/config/qutebrowser/quickmarks diff --git a/config/qutebrowser/qutebrowser b/config/qutebrowser/qutebrowser new file mode 120000 index 0000000..e65b4fc --- /dev/null +++ b/config/qutebrowser/qutebrowser @@ -0,0 +1 @@ +/home/tmu/dotfiles/config/qutebrowser
\ No newline at end of file diff --git a/sway/config b/config/sway/config index 7150e18..7150e18 100644 --- a/sway/config +++ b/config/sway/config diff --git a/sway/otherwindow b/config/sway/otherwindow index e75c40d..e75c40d 100755 --- a/sway/otherwindow +++ b/config/sway/otherwindow diff --git a/sway/switch.py b/config/sway/switch.py index 479cf74..479cf74 100755 --- a/sway/switch.py +++ b/config/sway/switch.py diff --git a/sway/switch.sh b/config/sway/switch.sh index 62751b8..62751b8 100755 --- a/sway/switch.sh +++ b/config/sway/switch.sh diff --git a/sway/toEmacs.sh b/config/sway/toEmacs.sh index aacf2c1..aacf2c1 100755 --- a/sway/toEmacs.sh +++ b/config/sway/toEmacs.sh diff --git a/vimb/_style.css b/config/vimb/_style.css index a824e29..a824e29 100644 --- a/vimb/_style.css +++ b/config/vimb/_style.css diff --git a/vimb/config b/config/vimb/config index 4e23902..4e23902 100644 --- a/vimb/config +++ b/config/vimb/config diff --git a/vimb/scripts.js b/config/vimb/scripts.js index b0698dc..b0698dc 100644 --- a/vimb/scripts.js +++ b/config/vimb/scripts.js diff --git a/vimb/vimb/_style.css b/config/vimb/vimb/_style.css index a824e29..a824e29 100644 --- a/vimb/vimb/_style.css +++ b/config/vimb/vimb/_style.css diff --git a/vimb/vimb/config b/config/vimb/vimb/config index 7560e4d..7560e4d 100644 --- a/vimb/vimb/config +++ b/config/vimb/vimb/config diff --git a/waybar/config b/config/waybar/config index 8951fa3..8951fa3 100644 --- a/waybar/config +++ b/config/waybar/config diff --git a/waybar/mediaplayer.py b/config/waybar/mediaplayer.py index 1630d97..1630d97 100755 --- a/waybar/mediaplayer.py +++ b/config/waybar/mediaplayer.py diff --git a/waybar/style.css b/config/waybar/style.css index 0a72916..0a72916 100644 --- a/waybar/style.css +++ b/config/waybar/style.css diff --git a/xmobarrc b/config/xmobarrc index 1f57a24..1f57a24 100644 --- a/xmobarrc +++ b/config/xmobarrc diff --git a/xmonad/xmonad.cabal b/config/xmonad/xmonad.cabal index 774c21f..774c21f 100644 --- a/xmonad/xmonad.cabal +++ b/config/xmonad/xmonad.cabal diff --git a/xmonad/xmonad.hs b/config/xmonad/xmonad.hs index 77dc3be..77dc3be 100644 --- a/xmonad/xmonad.hs +++ b/config/xmonad/xmonad.hs diff --git a/dwm/dwm-6.6.tar.gz b/dwm/dwm-6.6.tar.gz Binary files differdeleted file mode 100644 index 966b256..0000000 --- a/dwm/dwm-6.6.tar.gz +++ /dev/null diff --git a/dwm/dwm-6.6/LICENSE b/dwm/dwm-6.6/LICENSE deleted file mode 100644 index 995172f..0000000 --- a/dwm/dwm-6.6/LICENSE +++ /dev/null @@ -1,38 +0,0 @@ -MIT/X Consortium License - -© 2006-2019 Anselm R Garbe <anselm@garbe.ca> -© 2006-2009 Jukka Salmi <jukka at salmi dot ch> -© 2006-2007 Sander van Dijk <a dot h dot vandijk at gmail dot com> -© 2007-2011 Peter Hartlich <sgkkr at hartlich dot com> -© 2007-2009 Szabolcs Nagy <nszabolcs at gmail dot com> -© 2007-2009 Christof Musik <christof at sendfax dot de> -© 2007-2009 Premysl Hruby <dfenze at gmail dot com> -© 2007-2008 Enno Gottox Boland <gottox at s01 dot de> -© 2008 Martin Hurton <martin dot hurton at gmail dot com> -© 2008 Neale Pickett <neale dot woozle dot org> -© 2009 Mate Nagy <mnagy at port70 dot net> -© 2010-2016 Hiltjo Posthuma <hiltjo@codemadness.org> -© 2010-2012 Connor Lane Smith <cls@lubutu.com> -© 2011 Christoph Lohmann <20h@r-36.net> -© 2015-2016 Quentin Rameau <quinq@fifth.space> -© 2015-2016 Eric Pruitt <eric.pruitt@gmail.com> -© 2016-2017 Markus Teich <markus.teich@stusta.mhn.de> -© 2020-2022 Chris Down <chris@chrisdown.name> - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/dwm/dwm-6.6/Makefile b/dwm/dwm-6.6/Makefile deleted file mode 100644 index ffa69b4..0000000 --- a/dwm/dwm-6.6/Makefile +++ /dev/null @@ -1,45 +0,0 @@ -# dwm - dynamic window manager -# See LICENSE file for copyright and license details. - -include config.mk - -SRC = drw.c dwm.c util.c -OBJ = ${SRC:.c=.o} - -all: dwm - -.c.o: - ${CC} -c ${CFLAGS} $< - -${OBJ}: config.h config.mk - -config.h: - cp config.def.h $@ - -dwm: ${OBJ} - ${CC} -o $@ ${OBJ} ${LDFLAGS} - -clean: - rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz - -dist: clean - mkdir -p dwm-${VERSION} - cp -R LICENSE Makefile README config.def.h config.mk\ - dwm.1 drw.h util.h ${SRC} dwm.png transient.c dwm-${VERSION} - tar -cf dwm-${VERSION}.tar dwm-${VERSION} - gzip dwm-${VERSION}.tar - rm -rf dwm-${VERSION} - -install: all - mkdir -p ${DESTDIR}${PREFIX}/bin - cp -f dwm ${DESTDIR}${PREFIX}/bin - chmod 755 ${DESTDIR}${PREFIX}/bin/dwm - mkdir -p ${DESTDIR}${MANPREFIX}/man1 - sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1 - chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1 - -uninstall: - rm -f ${DESTDIR}${PREFIX}/bin/dwm\ - ${DESTDIR}${MANPREFIX}/man1/dwm.1 - -.PHONY: all clean dist install uninstall diff --git a/dwm/dwm-6.6/README b/dwm/dwm-6.6/README deleted file mode 100644 index 95d4fd0..0000000 --- a/dwm/dwm-6.6/README +++ /dev/null @@ -1,48 +0,0 @@ -dwm - dynamic window manager -============================ -dwm is an extremely fast, small, and dynamic window manager for X. - - -Requirements ------------- -In order to build dwm you need the Xlib header files. - - -Installation ------------- -Edit config.mk to match your local setup (dwm is installed into -the /usr/local namespace by default). - -Afterwards enter the following command to build and install dwm (if -necessary as root): - - make clean install - - -Running dwm ------------ -Add the following line to your .xinitrc to start dwm using startx: - - exec dwm - -In order to connect dwm to a specific display, make sure that -the DISPLAY environment variable is set correctly, e.g.: - - DISPLAY=foo.bar:1 exec dwm - -(This will start dwm on display :1 of the host foo.bar.) - -In order to display status info in the bar, you can do something -like this in your .xinitrc: - - while xsetroot -name "`date` `uptime | sed 's/.*,//'`" - do - sleep 1 - done & - exec dwm - - -Configuration -------------- -The configuration of dwm is done by creating a custom config.h -and (re)compiling the source code. diff --git a/dwm/dwm-6.6/config.def.h b/dwm/dwm-6.6/config.def.h deleted file mode 100644 index 7989be8..0000000 --- a/dwm/dwm-6.6/config.def.h +++ /dev/null @@ -1,136 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -#include <X11/XF86keysym.h> - -/* appearance */ -static const unsigned int borderpx = 1; /* border pixel of windows */ -static const unsigned int snap = 1; /* snap pixel */ -static const int showbar = 1; /* 0 means no bar */ -static const int topbar = 1; /* 0 means bottom bar */ -static const char *fonts[] = { "monospace:size=10" }; -static const char dmenufont[] = "monospace:size=10"; -static const char col_gray1[] = "#222222"; -static const char col_gray2[] = "#444444"; -static const char col_gray3[] = "#bbbbbb"; -static const char col_gray4[] = "#eeeeee"; -static const char col_purple[] = "#6904f7"; -static const char *colors[][3] = { - /* fg bg border */ - [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, - [SchemeSel] = { col_gray4, col_purple, col_purple }, -}; - -/* tagging */ -static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; - -static const Rule rules[] = { - /* xprop(1): - * WM_CLASS(STRING) = instance, class - * WM_NAME(STRING) = title - */ - /* class instance title tags mask isfloating monitor */ - { "Gimp", NULL, NULL, 0, 1, -1 }, - { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, -}; - -/* layout(s) */ -static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ -static const int nmaster = 1; /* number of clients in master area */ -static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ -static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ - -static const Layout layouts[] = { - /* symbol arrange function */ - { "[]=", tile }, /* first entry is default */ - { "><>", NULL }, /* no layout function means floating behavior */ - { "[M]", monocle }, -}; - -/* key definitions */ -#define MODKEY Mod4Mask -#define TAGKEYS(KEY,TAG) \ - { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ - { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ - { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ - { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, - -/* helper for spawning shell commands in the pre dwm-5.0 fashion */ -#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } - -/* commands */ -static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ -static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_purple, "-sf", col_gray4, NULL }; -static const char *termcmd[] = { "tmuterm", NULL }; -static const char *browsercmd[] = { "tmubrowse", NULL }; -static const char *bupcmd[] = { "brightnessup", NULL }; -static const char *bdowncmd[] = { "brightnessdown", NULL }; -static const char *bmaxcmd[] = { "brightnessmax", NULL }; -static const char *upvol[] = { "volumeup", NULL }; -static const char *downvol[] = { "volumedown", NULL }; -static const char *mutevol[] = { "volumemute", NULL }; - -#include "movestack.c" -static const Key keys[] = { - /* modifier key function argument */ - { MODKEY, XK_d, spawn, {.v = dmenucmd } }, - { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, - { MODKEY, XK_e, spawn, {.v = browsercmd } }, - { 0, XF86XK_MonBrightnessUp, spawn, {.v = bupcmd } }, - { 0, XF86XK_MonBrightnessDown, spawn, {.v = bdowncmd } }, - { 0, XF86XK_Display, spawn, {.v = bmaxcmd} }, - { 0, XF86XK_AudioLowerVolume, spawn, {.v = downvol } }, - { 0, XF86XK_AudioMute, spawn, {.v = mutevol } }, - { 0, XF86XK_AudioRaiseVolume, spawn, {.v = upvol } }, - { MODKEY, XK_b, togglebar, {0} }, - { MODKEY, XK_j, focusstack, {.i = +1 } }, - { MODKEY, XK_k, focusstack, {.i = -1 } }, - { MODKEY, XK_i, incnmaster, {.i = +1 } }, - { MODKEY, XK_o, incnmaster, {.i = -1 } }, - { MODKEY, XK_h, setmfact, {.f = -0.05} }, - { MODKEY, XK_l, setmfact, {.f = +0.05} }, - { MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } }, - { MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } }, - { MODKEY, XK_Return, zoom, {0} }, - { MODKEY, XK_Tab, view, {0} }, - { MODKEY, XK_w, selectclient, {0} }, - { MODKEY|ShiftMask, XK_c, killclient, {0} }, - { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, - { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, - { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, - { MODKEY, XK_space, setlayout, {0} }, - { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, - { MODKEY, XK_0, view, {.ui = ~0 } }, - { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, - { MODKEY, XK_comma, focusmon, {.i = -1 } }, - { MODKEY, XK_period, focusmon, {.i = +1 } }, - { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, - { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, - TAGKEYS( XK_1, 0) - TAGKEYS( XK_2, 1) - TAGKEYS( XK_3, 2) - TAGKEYS( XK_4, 3) - TAGKEYS( XK_5, 4) - TAGKEYS( XK_6, 5) - TAGKEYS( XK_7, 6) - TAGKEYS( XK_8, 7) - TAGKEYS( XK_9, 8) - { MODKEY|ShiftMask, XK_q, quitprompt, {0} }, -}; - -/* button definitions */ -/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ -static const Button buttons[] = { - /* click event mask button function argument */ - { ClkLtSymbol, 0, Button1, setlayout, {0} }, - { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, - { ClkWinTitle, 0, Button2, zoom, {0} }, - { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, - { ClkClientWin, MODKEY, Button1, movemouse, {0} }, - { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, - { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, - { ClkTagBar, 0, Button1, view, {0} }, - { ClkTagBar, 0, Button3, toggleview, {0} }, - { ClkTagBar, MODKEY, Button1, tag, {0} }, - { ClkTagBar, MODKEY, Button3, toggletag, {0} }, -}; - diff --git a/dwm/dwm-6.6/config.mk b/dwm/dwm-6.6/config.mk deleted file mode 100644 index e3a2826..0000000 --- a/dwm/dwm-6.6/config.mk +++ /dev/null @@ -1,39 +0,0 @@ -# dwm version -VERSION = 6.6 - -# Customize below to fit your system - -# paths -PREFIX = ${HOME}/.local -MANPREFIX = ${PREFIX}/share/man - -X11INC = /usr/X11R6/include -X11LIB = /usr/X11R6/lib - -# Xinerama, comment if you don't want it -XINERAMALIBS = -lXinerama -XINERAMAFLAGS = -DXINERAMA - -# freetype -FREETYPELIBS = -lfontconfig -lXft -FREETYPEINC = /usr/include/freetype2 -# OpenBSD (uncomment) -#FREETYPEINC = ${X11INC}/freetype2 -#MANPREFIX = ${PREFIX}/man - -# includes and libs -INCS = -I${X11INC} -I${FREETYPEINC} -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} - -# flags -CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} -#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} -CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} -LDFLAGS = ${LIBS} - -# Solaris -#CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\" -#LDFLAGS = ${LIBS} - -# compiler and linker -CC = cc diff --git a/dwm/dwm-6.6/drw.c b/dwm/dwm-6.6/drw.c deleted file mode 100644 index c41e6af..0000000 --- a/dwm/dwm-6.6/drw.c +++ /dev/null @@ -1,448 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <X11/Xlib.h> -#include <X11/Xft/Xft.h> - -#include "drw.h" -#include "util.h" - -#define UTF_INVALID 0xFFFD - -static int -utf8decode(const char *s_in, long *u, int *err) -{ - static const unsigned char lens[] = { - /* 0XXXX */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - /* 10XXX */ 0, 0, 0, 0, 0, 0, 0, 0, /* invalid */ - /* 110XX */ 2, 2, 2, 2, - /* 1110X */ 3, 3, - /* 11110 */ 4, - /* 11111 */ 0, /* invalid */ - }; - static const unsigned char leading_mask[] = { 0x7F, 0x1F, 0x0F, 0x07 }; - static const unsigned int overlong[] = { 0x0, 0x80, 0x0800, 0x10000 }; - - const unsigned char *s = (const unsigned char *)s_in; - int len = lens[*s >> 3]; - *u = UTF_INVALID; - *err = 1; - if (len == 0) - return 1; - - long cp = s[0] & leading_mask[len - 1]; - for (int i = 1; i < len; ++i) { - if (s[i] == '\0' || (s[i] & 0xC0) != 0x80) - return i; - cp = (cp << 6) | (s[i] & 0x3F); - } - /* out of range, surrogate, overlong encoding */ - if (cp > 0x10FFFF || (cp >> 11) == 0x1B || cp < overlong[len - 1]) - return len; - - *err = 0; - *u = cp; - return len; -} - -Drw * -drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) -{ - Drw *drw = ecalloc(1, sizeof(Drw)); - - drw->dpy = dpy; - drw->screen = screen; - drw->root = root; - drw->w = w; - drw->h = h; - drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); - drw->gc = XCreateGC(dpy, root, 0, NULL); - XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); - - return drw; -} - -void -drw_resize(Drw *drw, unsigned int w, unsigned int h) -{ - if (!drw) - return; - - drw->w = w; - drw->h = h; - if (drw->drawable) - XFreePixmap(drw->dpy, drw->drawable); - drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); -} - -void -drw_free(Drw *drw) -{ - XFreePixmap(drw->dpy, drw->drawable); - XFreeGC(drw->dpy, drw->gc); - drw_fontset_free(drw->fonts); - free(drw); -} - -/* This function is an implementation detail. Library users should use - * drw_fontset_create instead. - */ -static Fnt * -xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) -{ - Fnt *font; - XftFont *xfont = NULL; - FcPattern *pattern = NULL; - - if (fontname) { - /* Using the pattern found at font->xfont->pattern does not yield the - * same substitution results as using the pattern returned by - * FcNameParse; using the latter results in the desired fallback - * behaviour whereas the former just results in missing-character - * rectangles being drawn, at least with some fonts. */ - if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) { - fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname); - return NULL; - } - if (!(pattern = FcNameParse((FcChar8 *) fontname))) { - fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname); - XftFontClose(drw->dpy, xfont); - return NULL; - } - } else if (fontpattern) { - if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { - fprintf(stderr, "error, cannot load font from pattern.\n"); - return NULL; - } - } else { - die("no font specified."); - } - - font = ecalloc(1, sizeof(Fnt)); - font->xfont = xfont; - font->pattern = pattern; - font->h = xfont->ascent + xfont->descent; - font->dpy = drw->dpy; - - return font; -} - -static void -xfont_free(Fnt *font) -{ - if (!font) - return; - if (font->pattern) - FcPatternDestroy(font->pattern); - XftFontClose(font->dpy, font->xfont); - free(font); -} - -Fnt* -drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) -{ - Fnt *cur, *ret = NULL; - size_t i; - - if (!drw || !fonts) - return NULL; - - for (i = 1; i <= fontcount; i++) { - if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) { - cur->next = ret; - ret = cur; - } - } - return (drw->fonts = ret); -} - -void -drw_fontset_free(Fnt *font) -{ - if (font) { - drw_fontset_free(font->next); - xfont_free(font); - } -} - -void -drw_clr_create(Drw *drw, Clr *dest, const char *clrname) -{ - if (!drw || !dest || !clrname) - return; - - if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), - DefaultColormap(drw->dpy, drw->screen), - clrname, dest)) - die("error, cannot allocate color '%s'", clrname); -} - -/* Wrapper to create color schemes. The caller has to call free(3) on the - * returned color scheme when done using it. */ -Clr * -drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) -{ - size_t i; - Clr *ret; - - /* need at least two colors for a scheme */ - if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor)))) - return NULL; - - for (i = 0; i < clrcount; i++) - drw_clr_create(drw, &ret[i], clrnames[i]); - return ret; -} - -void -drw_setfontset(Drw *drw, Fnt *set) -{ - if (drw) - drw->fonts = set; -} - -void -drw_setscheme(Drw *drw, Clr *scm) -{ - if (drw) - drw->scheme = scm; -} - -void -drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) -{ - if (!drw || !drw->scheme) - return; - XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel); - if (filled) - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); - else - XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1); -} - -int -drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert) -{ - int ty, ellipsis_x = 0; - unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len, hash, h0, h1; - XftDraw *d = NULL; - Fnt *usedfont, *curfont, *nextfont; - int utf8strlen, utf8charlen, utf8err, render = x || y || w || h; - long utf8codepoint = 0; - const char *utf8str; - FcCharSet *fccharset; - FcPattern *fcpattern; - FcPattern *match; - XftResult result; - int charexists = 0, overflow = 0; - /* keep track of a couple codepoints for which we have no match. */ - static unsigned int nomatches[128], ellipsis_width, invalid_width; - static const char invalid[] = "�"; - - if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts) - return 0; - - if (!render) { - w = invert ? invert : ~invert; - } else { - XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); - if (w < lpad) - return x + w; - d = XftDrawCreate(drw->dpy, drw->drawable, - DefaultVisual(drw->dpy, drw->screen), - DefaultColormap(drw->dpy, drw->screen)); - x += lpad; - w -= lpad; - } - - usedfont = drw->fonts; - if (!ellipsis_width && render) - ellipsis_width = drw_fontset_getwidth(drw, "..."); - if (!invalid_width && render) - invalid_width = drw_fontset_getwidth(drw, invalid); - while (1) { - ew = ellipsis_len = utf8err = utf8charlen = utf8strlen = 0; - utf8str = text; - nextfont = NULL; - while (*text) { - utf8charlen = utf8decode(text, &utf8codepoint, &utf8err); - for (curfont = drw->fonts; curfont; curfont = curfont->next) { - charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); - if (charexists) { - drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL); - if (ew + ellipsis_width <= w) { - /* keep track where the ellipsis still fits */ - ellipsis_x = x + ew; - ellipsis_w = w - ew; - ellipsis_len = utf8strlen; - } - - if (ew + tmpw > w) { - overflow = 1; - /* called from drw_fontset_getwidth_clamp(): - * it wants the width AFTER the overflow - */ - if (!render) - x += tmpw; - else - utf8strlen = ellipsis_len; - } else if (curfont == usedfont) { - text += utf8charlen; - utf8strlen += utf8err ? 0 : utf8charlen; - ew += utf8err ? 0 : tmpw; - } else { - nextfont = curfont; - } - break; - } - } - - if (overflow || !charexists || nextfont || utf8err) - break; - else - charexists = 0; - } - - if (utf8strlen) { - if (render) { - ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; - XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], - usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen); - } - x += ew; - w -= ew; - } - if (utf8err && (!render || invalid_width < w)) { - if (render) - drw_text(drw, x, y, w, h, 0, invalid, invert); - x += invalid_width; - w -= invalid_width; - } - if (render && overflow) - drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert); - - if (!*text || overflow) { - break; - } else if (nextfont) { - charexists = 0; - usedfont = nextfont; - } else { - /* Regardless of whether or not a fallback font is found, the - * character must be drawn. */ - charexists = 1; - - hash = (unsigned int)utf8codepoint; - hash = ((hash >> 16) ^ hash) * 0x21F0AAAD; - hash = ((hash >> 15) ^ hash) * 0xD35A2D97; - h0 = ((hash >> 15) ^ hash) % LENGTH(nomatches); - h1 = (hash >> 17) % LENGTH(nomatches); - /* avoid expensive XftFontMatch call when we know we won't find a match */ - if (nomatches[h0] == utf8codepoint || nomatches[h1] == utf8codepoint) - goto no_match; - - fccharset = FcCharSetCreate(); - FcCharSetAddChar(fccharset, utf8codepoint); - - if (!drw->fonts->pattern) { - /* Refer to the comment in xfont_create for more information. */ - die("the first font in the cache must be loaded from a font string."); - } - - fcpattern = FcPatternDuplicate(drw->fonts->pattern); - FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); - FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); - - FcConfigSubstitute(NULL, fcpattern, FcMatchPattern); - FcDefaultSubstitute(fcpattern); - match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result); - - FcCharSetDestroy(fccharset); - FcPatternDestroy(fcpattern); - - if (match) { - usedfont = xfont_create(drw, NULL, match); - if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) { - for (curfont = drw->fonts; curfont->next; curfont = curfont->next) - ; /* NOP */ - curfont->next = usedfont; - } else { - xfont_free(usedfont); - nomatches[nomatches[h0] ? h1 : h0] = utf8codepoint; -no_match: - usedfont = drw->fonts; - } - } - } - } - if (d) - XftDrawDestroy(d); - - return x + (render ? w : 0); -} - -void -drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) -{ - if (!drw) - return; - - XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y); - XSync(drw->dpy, False); -} - -unsigned int -drw_fontset_getwidth(Drw *drw, const char *text) -{ - if (!drw || !drw->fonts || !text) - return 0; - return drw_text(drw, 0, 0, 0, 0, 0, text, 0); -} - -unsigned int -drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n) -{ - unsigned int tmp = 0; - if (drw && drw->fonts && text && n) - tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n); - return MIN(n, tmp); -} - -void -drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) -{ - XGlyphInfo ext; - - if (!font || !text) - return; - - XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext); - if (w) - *w = ext.xOff; - if (h) - *h = font->h; -} - -Cur * -drw_cur_create(Drw *drw, int shape) -{ - Cur *cur; - - if (!drw || !(cur = ecalloc(1, sizeof(Cur)))) - return NULL; - - cur->cursor = XCreateFontCursor(drw->dpy, shape); - - return cur; -} - -void -drw_cur_free(Drw *drw, Cur *cursor) -{ - if (!cursor) - return; - - XFreeCursor(drw->dpy, cursor->cursor); - free(cursor); -} diff --git a/dwm/dwm-6.6/drw.h b/dwm/dwm-6.6/drw.h deleted file mode 100644 index 6471431..0000000 --- a/dwm/dwm-6.6/drw.h +++ /dev/null @@ -1,58 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -typedef struct { - Cursor cursor; -} Cur; - -typedef struct Fnt { - Display *dpy; - unsigned int h; - XftFont *xfont; - FcPattern *pattern; - struct Fnt *next; -} Fnt; - -enum { ColFg, ColBg, ColBorder }; /* Clr scheme index */ -typedef XftColor Clr; - -typedef struct { - unsigned int w, h; - Display *dpy; - int screen; - Window root; - Drawable drawable; - GC gc; - Clr *scheme; - Fnt *fonts; -} Drw; - -/* Drawable abstraction */ -Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); -void drw_resize(Drw *drw, unsigned int w, unsigned int h); -void drw_free(Drw *drw); - -/* Fnt abstraction */ -Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount); -void drw_fontset_free(Fnt* set); -unsigned int drw_fontset_getwidth(Drw *drw, const char *text); -unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n); -void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); - -/* Colorscheme abstraction */ -void drw_clr_create(Drw *drw, Clr *dest, const char *clrname); -Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount); - -/* Cursor abstraction */ -Cur *drw_cur_create(Drw *drw, int shape); -void drw_cur_free(Drw *drw, Cur *cursor); - -/* Drawing context manipulation */ -void drw_setfontset(Drw *drw, Fnt *set); -void drw_setscheme(Drw *drw, Clr *scm); - -/* Drawing functions */ -void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); -int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); - -/* Map functions */ -void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); diff --git a/dwm/dwm-6.6/dwm.1 b/dwm/dwm-6.6/dwm.1 deleted file mode 100644 index ddc8321..0000000 --- a/dwm/dwm-6.6/dwm.1 +++ /dev/null @@ -1,176 +0,0 @@ -.TH DWM 1 dwm\-VERSION -.SH NAME -dwm \- dynamic window manager -.SH SYNOPSIS -.B dwm -.RB [ \-v ] -.SH DESCRIPTION -dwm is a dynamic window manager for X. It manages windows in tiled, monocle -and floating layouts. Either layout can be applied dynamically, optimising the -environment for the application in use and the task performed. -.P -In tiled layouts windows are managed in a master and stacking area. The master -area on the left contains one window by default, and the stacking area on the -right contains all other windows. The number of master area windows can be -adjusted from zero to an arbitrary number. In monocle layout all windows are -maximised to the screen size. In floating layout windows can be resized and -moved freely. Dialog windows are always managed floating, regardless of the -layout applied. -.P -Windows are grouped by tags. Each window can be tagged with one or multiple -tags. Selecting certain tags displays all windows with these tags. -.P -Each screen contains a small status bar which displays all available tags, the -layout, the title of the focused window, and the text read from the root window -name property, if the screen is focused. A floating window is indicated with an -empty square and a maximised floating window is indicated with a filled square -before the windows title. The selected tags are indicated with a different -color. The tags of the focused window are indicated with a filled square in the -top left corner. The tags which are applied to one or more windows are -indicated with an empty square in the top left corner. -.P -dwm draws a small border around windows to indicate the focus state. -.SH OPTIONS -.TP -.B \-v -prints version information to stderr, then exits. -.SH USAGE -.SS Status bar -.TP -.B X root window name -is read and displayed in the status text area. It can be set with the -.BR xsetroot (1) -command. -.TP -.B Button1 -click on a tag label to display all windows with that tag, click on the layout -label toggles between tiled and floating layout. -.TP -.B Button3 -click on a tag label adds/removes all windows with that tag to/from the view. -.TP -.B Mod1\-Button1 -click on a tag label applies that tag to the focused window. -.TP -.B Mod1\-Button3 -click on a tag label adds/removes that tag to/from the focused window. -.SS Keyboard commands -.TP -.B Mod1\-Shift\-Return -Start -.BR st(1). -.TP -.B Mod1\-p -Spawn -.BR dmenu(1) -for launching other programs. -.TP -.B Mod1\-, -Focus previous screen, if any. -.TP -.B Mod1\-. -Focus next screen, if any. -.TP -.B Mod1\-Shift\-, -Send focused window to previous screen, if any. -.TP -.B Mod1\-Shift\-. -Send focused window to next screen, if any. -.TP -.B Mod1\-b -Toggles bar on and off. -.TP -.B Mod1\-t -Sets tiled layout. -.TP -.B Mod1\-f -Sets floating layout. -.TP -.B Mod1\-m -Sets monocle layout. -.TP -.B Mod1\-space -Toggles between current and previous layout. -.TP -.B Mod1\-j -Focus next window. -.TP -.B Mod1\-k -Focus previous window. -.TP -.B Mod1\-i -Increase number of windows in master area. -.TP -.B Mod1\-d -Decrease number of windows in master area. -.TP -.B Mod1\-l -Increase master area size. -.TP -.B Mod1\-h -Decrease master area size. -.TP -.B Mod1\-Return -Zooms/cycles focused window to/from master area (tiled layouts only). -.TP -.B Mod1\-Shift\-c -Close focused window. -.TP -.B Mod1\-Shift\-space -Toggle focused window between tiled and floating state. -.TP -.B Mod1\-Tab -Toggles to the previously selected tags. -.TP -.B Mod1\-Shift\-[1..n] -Apply nth tag to focused window. -.TP -.B Mod1\-Shift\-0 -Apply all tags to focused window. -.TP -.B Mod1\-Control\-Shift\-[1..n] -Add/remove nth tag to/from focused window. -.TP -.B Mod1\-[1..n] -View all windows with nth tag. -.TP -.B Mod1\-0 -View all windows with any tag. -.TP -.B Mod1\-Control\-[1..n] -Add/remove all windows with nth tag to/from the view. -.TP -.B Mod1\-Shift\-q -Quit dwm. -.SS Mouse commands -.TP -.B Mod1\-Button1 -Move focused window while dragging. Tiled windows will be toggled to the floating state. -.TP -.B Mod1\-Button2 -Toggles focused window between floating and tiled state. -.TP -.B Mod1\-Button3 -Resize focused window while dragging. Tiled windows will be toggled to the floating state. -.SH CUSTOMIZATION -dwm is customized by creating a custom config.h and (re)compiling the source -code. This keeps it fast, secure and simple. -.SH SEE ALSO -.BR dmenu (1), -.BR st (1) -.SH ISSUES -Java applications which use the XToolkit/XAWT backend may draw grey windows -only. The XToolkit/XAWT backend breaks ICCCM-compliance in recent JDK 1.5 and early -JDK 1.6 versions, because it assumes a reparenting window manager. Possible workarounds -are using JDK 1.4 (which doesn't contain the XToolkit/XAWT backend) or setting the -environment variable -.BR AWT_TOOLKIT=MToolkit -(to use the older Motif backend instead) or running -.B xprop -root -f _NET_WM_NAME 32a -set _NET_WM_NAME LG3D -or -.B wmname LG3D -(to pretend that a non-reparenting window manager is running that the -XToolkit/XAWT backend can recognize) or when using OpenJDK setting the environment variable -.BR _JAVA_AWT_WM_NONREPARENTING=1 . -.SH BUGS -Send all bug reports with a patch to hackers@suckless.org. diff --git a/dwm/dwm-6.6/dwm.c b/dwm/dwm-6.6/dwm.c deleted file mode 100644 index e090a53..0000000 --- a/dwm/dwm-6.6/dwm.c +++ /dev/null @@ -1,2277 +0,0 @@ -/* See LICENSE file for copyright and license details. - * - * dynamic window manager is designed like any other X client as well. It is - * driven through handling X events. In contrast to other X clients, a window - * manager selects for SubstructureRedirectMask on the root window, to receive - * events about window (dis-)appearance. Only one X connection at a time is - * allowed to select for this event mask. - * - * The event handlers of dwm are organized in an array which is accessed - * whenever a new event has been fetched. This allows event dispatching - * in O(1) time. - * - * Each child of the root window is called a client, except windows which have - * set the override_redirect flag. Clients are organized in a linked client - * list on each monitor, the focus history is remembered through a stack list - * on each monitor. Each client contains a bit array to indicate the tags of a - * client. - * - * Keys and tagging rules are organized as arrays and defined in config.h. - * - * To understand everything else, start reading main(). - */ -#include <errno.h> -#include <locale.h> -#include <signal.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <X11/cursorfont.h> -#include <X11/keysym.h> -#include <X11/Xatom.h> -#include <X11/Xlib.h> -#include <X11/Xproto.h> -#include <X11/Xutil.h> -#ifdef XINERAMA -#include <X11/extensions/Xinerama.h> -#endif /* XINERAMA */ -#include <X11/Xft/Xft.h> - -#include "drw.h" -#include "util.h" - -/* macros */ -#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) -#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) -#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ - * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) -#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) -#define MOUSEMASK (BUTTONMASK|PointerMotionMask) -#define WIDTH(X) ((X)->w + 2 * (X)->bw) -#define HEIGHT(X) ((X)->h + 2 * (X)->bw) -#define TAGMASK ((1 << LENGTH(tags)) - 1) -#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) - -/* enums */ -enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ -enum { SchemeNorm, SchemeSel }; /* color schemes */ -enum { NetSupported, NetWMName, NetWMState, NetWMCheck, - NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ -enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ -enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, - ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ - -typedef union { - int i; - unsigned int ui; - float f; - const void *v; -} Arg; - -typedef struct { - unsigned int click; - unsigned int mask; - unsigned int button; - void (*func)(const Arg *arg); - const Arg arg; -} Button; - -typedef struct Monitor Monitor; -typedef struct Client Client; -struct Client { - char name[256]; - float mina, maxa; - int x, y, w, h; - int oldx, oldy, oldw, oldh; - int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid; - int bw, oldbw; - unsigned int tags; - int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; - Client *next; - Client *snext; - Monitor *mon; - Window win; -}; - -typedef struct { - unsigned int mod; - KeySym keysym; - void (*func)(const Arg *); - const Arg arg; -} Key; - -typedef struct { - const char *symbol; - void (*arrange)(Monitor *); -} Layout; - -struct Monitor { - char ltsymbol[16]; - float mfact; - int nmaster; - int num; - int by; /* bar geometry */ - int mx, my, mw, mh; /* screen size */ - int wx, wy, ww, wh; /* window area */ - unsigned int seltags; - unsigned int sellt; - unsigned int tagset[2]; - int showbar; - int topbar; - Client *clients; - Client *sel; - Client *stack; - Monitor *next; - Window barwin; - const Layout *lt[2]; -}; - -typedef struct { - const char *class; - const char *instance; - const char *title; - unsigned int tags; - int isfloating; - int monitor; -} Rule; - -/* function declarations */ -static void applyrules(Client *c); -static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); -static void arrange(Monitor *m); -static void arrangemon(Monitor *m); -static void attach(Client *c); -static void attachstack(Client *c); -static void buttonpress(XEvent *e); -static void checkotherwm(void); -static void cleanup(void); -static void cleanupmon(Monitor *mon); -static void clientmessage(XEvent *e); -static void configure(Client *c); -static void configurenotify(XEvent *e); -static void configurerequest(XEvent *e); -static Monitor *createmon(void); -static void destroynotify(XEvent *e); -static void detach(Client *c); -static void detachstack(Client *c); -static Monitor *dirtomon(int dir); -static void drawbar(Monitor *m); -static void drawbars(void); -static void expose(XEvent *e); -static void focus(Client *c); -static void focusin(XEvent *e); -static void focusmon(const Arg *arg); -static void focusstack(const Arg *arg); -static Atom getatomprop(Client *c, Atom prop); -static int getrootptr(int *x, int *y); -static long getstate(Window w); -static int gettextprop(Window w, Atom atom, char *text, unsigned int size); -static void grabbuttons(Client *c, int focused); -static void grabkeys(void); -static void incnmaster(const Arg *arg); -static void keypress(XEvent *e); -static void killclient(const Arg *arg); -static void manage(Window w, XWindowAttributes *wa); -static void mappingnotify(XEvent *e); -static void maprequest(XEvent *e); -static void monocle(Monitor *m); -static void motionnotify(XEvent *e); -static void movemouse(const Arg *arg); -static Client *nexttiled(Client *c); -static void pop(Client *c); -static void propertynotify(XEvent *e); -static void quit(const Arg *arg); -static void quitprompt(const Arg *arg); -static Monitor *recttomon(int x, int y, int w, int h); -static void resize(Client *c, int x, int y, int w, int h, int interact); -static void resizeclient(Client *c, int x, int y, int w, int h); -static void resizemouse(const Arg *arg); -static void restack(Monitor *m); -static void run(void); -static void scan(void); -static void selectclient(const Arg *arg); -static int sendevent(Client *c, Atom proto); -static void sendmon(Client *c, Monitor *m); -static void setclientstate(Client *c, long state); -static void setfocus(Client *c); -static void setfullscreen(Client *c, int fullscreen); -static void setlayout(const Arg *arg); -static void setmfact(const Arg *arg); -static void setup(void); -static void seturgent(Client *c, int urg); -static void showhide(Client *c); -static void spawn(const Arg *arg); -static void tag(const Arg *arg); -static void tagmon(const Arg *arg); -static void tile(Monitor *m); -static void togglebar(const Arg *arg); -static void togglefloating(const Arg *arg); -static void toggletag(const Arg *arg); -static void toggleview(const Arg *arg); -static void unfocus(Client *c, int setfocus); -static void unmanage(Client *c, int destroyed); -static void unmapnotify(XEvent *e); -static void updatebarpos(Monitor *m); -static void updatebars(void); -static void updateclientlist(void); -static int updategeom(void); -static void updatenumlockmask(void); -static void updatesizehints(Client *c); -static void updatestatus(void); -static void updatetitle(Client *c); -static void updatewindowtype(Client *c); -static void updatewmhints(Client *c); -static void view(const Arg *arg); -static void warp(const Client *c); -static Client *wintoclient(Window w); -static Monitor *wintomon(Window w); -static int xerror(Display *dpy, XErrorEvent *ee); -static int xerrordummy(Display *dpy, XErrorEvent *ee); -static int xerrorstart(Display *dpy, XErrorEvent *ee); -static void zoom(const Arg *arg); - -/* variables */ -static const char broken[] = "broken"; -static char stext[256]; -static int screen; -static int sw, sh; /* X display screen geometry width, height */ -static int bh; /* bar height */ -static int lrpad; /* sum of left and right padding for text */ -static int (*xerrorxlib)(Display *, XErrorEvent *); -static unsigned int numlockmask = 0; -static void (*handler[LASTEvent]) (XEvent *) = { - [ButtonPress] = buttonpress, - [ClientMessage] = clientmessage, - [ConfigureRequest] = configurerequest, - [ConfigureNotify] = configurenotify, - [DestroyNotify] = destroynotify, - [Expose] = expose, - [FocusIn] = focusin, - [KeyPress] = keypress, - [MappingNotify] = mappingnotify, - [MapRequest] = maprequest, - [MotionNotify] = motionnotify, - [PropertyNotify] = propertynotify, - [UnmapNotify] = unmapnotify -}; -static Atom wmatom[WMLast], netatom[NetLast]; -static int running = 1; -static int restart = 1; -static Cur *cursor[CurLast]; -static Clr **scheme; -static Display *dpy; -static Drw *drw; -static Monitor *mons, *selmon; -static Window root, wmcheckwin; - -/* configuration, allows nested code to access above variables */ -#include "config.h" - -/* compile-time check if all tags fit into an unsigned int bit array. */ -struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; - -/* function implementations */ -void -applyrules(Client *c) -{ - const char *class, *instance; - unsigned int i; - const Rule *r; - Monitor *m; - XClassHint ch = { NULL, NULL }; - - /* rule matching */ - c->isfloating = 0; - c->tags = 0; - XGetClassHint(dpy, c->win, &ch); - class = ch.res_class ? ch.res_class : broken; - instance = ch.res_name ? ch.res_name : broken; - - for (i = 0; i < LENGTH(rules); i++) { - r = &rules[i]; - if ((!r->title || strstr(c->name, r->title)) - && (!r->class || strstr(class, r->class)) - && (!r->instance || strstr(instance, r->instance))) - { - c->isfloating = r->isfloating; - c->tags |= r->tags; - for (m = mons; m && m->num != r->monitor; m = m->next); - if (m) - c->mon = m; - } - } - if (ch.res_class) - XFree(ch.res_class); - if (ch.res_name) - XFree(ch.res_name); - c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; -} - -int -applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact) -{ - int baseismin; - Monitor *m = c->mon; - - /* set minimum possible */ - *w = MAX(1, *w); - *h = MAX(1, *h); - if (interact) { - if (*x > sw) - *x = sw - WIDTH(c); - if (*y > sh) - *y = sh - HEIGHT(c); - if (*x + *w + 2 * c->bw < 0) - *x = 0; - if (*y + *h + 2 * c->bw < 0) - *y = 0; - } else { - if (*x >= m->wx + m->ww) - *x = m->wx + m->ww - WIDTH(c); - if (*y >= m->wy + m->wh) - *y = m->wy + m->wh - HEIGHT(c); - if (*x + *w + 2 * c->bw <= m->wx) - *x = m->wx; - if (*y + *h + 2 * c->bw <= m->wy) - *y = m->wy; - } - if (*h < bh) - *h = bh; - if (*w < bh) - *w = bh; - if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) { - if (!c->hintsvalid) - updatesizehints(c); - /* see last two sentences in ICCCM 4.1.2.3 */ - baseismin = c->basew == c->minw && c->baseh == c->minh; - if (!baseismin) { /* temporarily remove base dimensions */ - *w -= c->basew; - *h -= c->baseh; - } - /* adjust for aspect limits */ - if (c->mina > 0 && c->maxa > 0) { - if (c->maxa < (float)*w / *h) - *w = *h * c->maxa + 0.5; - else if (c->mina < (float)*h / *w) - *h = *w * c->mina + 0.5; - } - if (baseismin) { /* increment calculation requires this */ - *w -= c->basew; - *h -= c->baseh; - } - /* adjust for increment value */ - if (c->incw) - *w -= *w % c->incw; - if (c->inch) - *h -= *h % c->inch; - /* restore base dimensions */ - *w = MAX(*w + c->basew, c->minw); - *h = MAX(*h + c->baseh, c->minh); - if (c->maxw) - *w = MIN(*w, c->maxw); - if (c->maxh) - *h = MIN(*h, c->maxh); - } - return *x != c->x || *y != c->y || *w != c->w || *h != c->h; -} - -void -arrange(Monitor *m) -{ - if (m) - showhide(m->stack); - else for (m = mons; m; m = m->next) - showhide(m->stack); - if (m) { - arrangemon(m); - restack(m); - } else for (m = mons; m; m = m->next) - arrangemon(m); -} - -void -arrangemon(Monitor *m) -{ - strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); - if (m->lt[m->sellt]->arrange) - m->lt[m->sellt]->arrange(m); -} - -void -attach(Client *c) -{ - c->next = c->mon->clients; - c->mon->clients = c; -} - -void -attachstack(Client *c) -{ - c->snext = c->mon->stack; - c->mon->stack = c; -} - -void -buttonpress(XEvent *e) -{ - unsigned int i, x, click; - Arg arg = {0}; - Client *c; - Monitor *m; - XButtonPressedEvent *ev = &e->xbutton; - - click = ClkRootWin; - /* focus monitor if necessary */ - if ((m = wintomon(ev->window)) && m != selmon) { - unfocus(selmon->sel, 1); - selmon = m; - focus(NULL); - } - if (ev->window == selmon->barwin) { - i = x = 0; - do - x += TEXTW(tags[i]); - while (ev->x >= x && ++i < LENGTH(tags)); - if (i < LENGTH(tags)) { - click = ClkTagBar; - arg.ui = 1 << i; - } else if (ev->x < x + TEXTW(selmon->ltsymbol)) - click = ClkLtSymbol; - else if (ev->x > selmon->ww - (int)TEXTW(stext)) - click = ClkStatusText; - else - click = ClkWinTitle; - } else if ((c = wintoclient(ev->window))) { - focus(c); - restack(selmon); - XAllowEvents(dpy, ReplayPointer, CurrentTime); - click = ClkClientWin; - } - for (i = 0; i < LENGTH(buttons); i++) - if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button - && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) - buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); -} - -void -checkotherwm(void) -{ - xerrorxlib = XSetErrorHandler(xerrorstart); - /* this causes an error if some other window manager is running */ - XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask); - XSync(dpy, False); - XSetErrorHandler(xerror); - XSync(dpy, False); -} - -void -cleanup(void) -{ - Arg a = {.ui = ~0}; - Layout foo = { "", NULL }; - Monitor *m; - size_t i; - - view(&a); - selmon->lt[selmon->sellt] = &foo; - for (m = mons; m; m = m->next) - while (m->stack) - unmanage(m->stack, 0); - XUngrabKey(dpy, AnyKey, AnyModifier, root); - while (mons) - cleanupmon(mons); - for (i = 0; i < CurLast; i++) - drw_cur_free(drw, cursor[i]); - for (i = 0; i < LENGTH(colors); i++) - free(scheme[i]); - free(scheme); - XDestroyWindow(dpy, wmcheckwin); - drw_free(drw); - XSync(dpy, False); - XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); - XDeleteProperty(dpy, root, netatom[NetActiveWindow]); -} - -void -cleanupmon(Monitor *mon) -{ - Monitor *m; - - if (mon == mons) - mons = mons->next; - else { - for (m = mons; m && m->next != mon; m = m->next); - m->next = mon->next; - } - XUnmapWindow(dpy, mon->barwin); - XDestroyWindow(dpy, mon->barwin); - free(mon); -} - -void -clientmessage(XEvent *e) -{ - XClientMessageEvent *cme = &e->xclient; - Client *c = wintoclient(cme->window); - - if (!c) - return; - if (cme->message_type == netatom[NetWMState]) { - if (cme->data.l[1] == netatom[NetWMFullscreen] - || cme->data.l[2] == netatom[NetWMFullscreen]) - setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */ - || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); - } else if (cme->message_type == netatom[NetActiveWindow]) { - if (c != selmon->sel && !c->isurgent) - seturgent(c, 1); - } -} - -void -configure(Client *c) -{ - XConfigureEvent ce; - - ce.type = ConfigureNotify; - ce.display = dpy; - ce.event = c->win; - ce.window = c->win; - ce.x = c->x; - ce.y = c->y; - ce.width = c->w; - ce.height = c->h; - ce.border_width = c->bw; - ce.above = None; - ce.override_redirect = False; - XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce); -} - -void -configurenotify(XEvent *e) -{ - Monitor *m; - Client *c; - XConfigureEvent *ev = &e->xconfigure; - int dirty; - - /* TODO: updategeom handling sucks, needs to be simplified */ - if (ev->window == root) { - dirty = (sw != ev->width || sh != ev->height); - sw = ev->width; - sh = ev->height; - if (updategeom() || dirty) { - drw_resize(drw, sw, bh); - updatebars(); - for (m = mons; m; m = m->next) { - for (c = m->clients; c; c = c->next) - if (c->isfullscreen) - resizeclient(c, m->mx, m->my, m->mw, m->mh); - XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); - } - focus(NULL); - arrange(NULL); - } - } -} - -void -configurerequest(XEvent *e) -{ - Client *c; - Monitor *m; - XConfigureRequestEvent *ev = &e->xconfigurerequest; - XWindowChanges wc; - - if ((c = wintoclient(ev->window))) { - if (ev->value_mask & CWBorderWidth) - c->bw = ev->border_width; - else if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) { - m = c->mon; - if (ev->value_mask & CWX) { - c->oldx = c->x; - c->x = m->mx + ev->x; - } - if (ev->value_mask & CWY) { - c->oldy = c->y; - c->y = m->my + ev->y; - } - if (ev->value_mask & CWWidth) { - c->oldw = c->w; - c->w = ev->width; - } - if (ev->value_mask & CWHeight) { - c->oldh = c->h; - c->h = ev->height; - } - if ((c->x + c->w) > m->mx + m->mw && c->isfloating) - c->x = m->mx + (m->mw / 2 - WIDTH(c) / 2); /* center in x direction */ - if ((c->y + c->h) > m->my + m->mh && c->isfloating) - c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */ - if ((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight))) - configure(c); - if (ISVISIBLE(c)) - XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); - } else - configure(c); - } else { - wc.x = ev->x; - wc.y = ev->y; - wc.width = ev->width; - wc.height = ev->height; - wc.border_width = ev->border_width; - wc.sibling = ev->above; - wc.stack_mode = ev->detail; - XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); - } - XSync(dpy, False); -} - -Monitor * -createmon(void) -{ - Monitor *m; - - m = ecalloc(1, sizeof(Monitor)); - m->tagset[0] = m->tagset[1] = 1; - m->mfact = mfact; - m->nmaster = nmaster; - m->showbar = showbar; - m->topbar = topbar; - m->lt[0] = &layouts[0]; - m->lt[1] = &layouts[1 % LENGTH(layouts)]; - strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); - return m; -} - -void -destroynotify(XEvent *e) -{ - Client *c; - XDestroyWindowEvent *ev = &e->xdestroywindow; - - if ((c = wintoclient(ev->window))) - unmanage(c, 1); -} - -void -detach(Client *c) -{ - Client **tc; - - for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next); - *tc = c->next; -} - -void -detachstack(Client *c) -{ - Client **tc, *t; - - for (tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext); - *tc = c->snext; - - if (c == c->mon->sel) { - for (t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext); - c->mon->sel = t; - } -} - -Monitor * -dirtomon(int dir) -{ - Monitor *m = NULL; - - if (dir > 0) { - if (!(m = selmon->next)) - m = mons; - } else if (selmon == mons) - for (m = mons; m->next; m = m->next); - else - for (m = mons; m->next != selmon; m = m->next); - return m; -} - -void -drawbar(Monitor *m) -{ - int x, w, tw = 0; - int boxs = drw->fonts->h / 9; - int boxw = drw->fonts->h / 6 + 2; - unsigned int i, occ = 0, urg = 0; - Client *c; - - if (!m->showbar) - return; - - /* draw status first so it can be overdrawn by tags later */ - if (m == selmon) { /* status is only drawn on selected monitor */ - drw_setscheme(drw, scheme[SchemeNorm]); - tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ - drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0); - } - - for (c = m->clients; c; c = c->next) { - occ |= c->tags; - if (c->isurgent) - urg |= c->tags; - } - x = 0; - for (i = 0; i < LENGTH(tags); i++) { - w = TEXTW(tags[i]); - drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); - drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); - if (occ & 1 << i) - drw_rect(drw, x + boxs, boxs, boxw, boxw, - m == selmon && selmon->sel && selmon->sel->tags & 1 << i, - urg & 1 << i); - x += w; - } - w = TEXTW(m->ltsymbol); - drw_setscheme(drw, scheme[SchemeNorm]); - x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); - - if ((w = m->ww - tw - x) > bh) { - if (m->sel) { - drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); - drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); - if (m->sel->isfloating) - drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); - } else { - drw_setscheme(drw, scheme[SchemeNorm]); - drw_rect(drw, x, 0, w, bh, 1, 1); - } - } - drw_map(drw, m->barwin, 0, 0, m->ww, bh); -} - -void -drawbars(void) -{ - Monitor *m; - - for (m = mons; m; m = m->next) - drawbar(m); -} - -void -expose(XEvent *e) -{ - Monitor *m; - XExposeEvent *ev = &e->xexpose; - - if (ev->count == 0 && (m = wintomon(ev->window))) - drawbar(m); -} - -void -focus(Client *c) -{ - if (!c || !ISVISIBLE(c)) - for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); - if (selmon->sel && selmon->sel != c) - unfocus(selmon->sel, 0); - if (c) { - if (c->mon != selmon) - selmon = c->mon; - if (c->isurgent) - seturgent(c, 0); - detachstack(c); - attachstack(c); - grabbuttons(c, 1); - XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); - setfocus(c); - } else { - XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); - XDeleteProperty(dpy, root, netatom[NetActiveWindow]); - } - selmon->sel = c; - drawbars(); -} - -/* there are some broken focus acquiring clients needing extra handling */ -void -focusin(XEvent *e) -{ - XFocusChangeEvent *ev = &e->xfocus; - - if (selmon->sel && ev->window != selmon->sel->win) - setfocus(selmon->sel); -} - -void -focusmon(const Arg *arg) -{ - Monitor *m; - - if (!mons->next) - return; - if ((m = dirtomon(arg->i)) == selmon) - return; - unfocus(selmon->sel, 0); - selmon = m; - focus(NULL); - warp(selmon->sel); -} - -void -focusstack(const Arg *arg) -{ - Client *c = NULL, *i; - - if (!selmon->sel || (selmon->sel->isfullscreen && lockfullscreen)) - return; - if (arg->i > 0) { - for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); - if (!c) - for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next); - } else { - for (i = selmon->clients; i != selmon->sel; i = i->next) - if (ISVISIBLE(i)) - c = i; - if (!c) - for (; i; i = i->next) - if (ISVISIBLE(i)) - c = i; - } - if (c) { - focus(c); - restack(selmon); - } -} - -Atom -getatomprop(Client *c, Atom prop) -{ - int di; - unsigned long dl; - unsigned char *p = NULL; - Atom da, atom = None; - - if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, - &da, &di, &dl, &dl, &p) == Success && p) { - atom = *(Atom *)p; - XFree(p); - } - return atom; -} - -int -getrootptr(int *x, int *y) -{ - int di; - unsigned int dui; - Window dummy; - - return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui); -} - -long -getstate(Window w) -{ - int format; - long result = -1; - unsigned char *p = NULL; - unsigned long n, extra; - Atom real; - - if (XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], - &real, &format, &n, &extra, (unsigned char **)&p) != Success) - return -1; - if (n != 0) - result = *p; - XFree(p); - return result; -} - -int -gettextprop(Window w, Atom atom, char *text, unsigned int size) -{ - char **list = NULL; - int n; - XTextProperty name; - - if (!text || size == 0) - return 0; - text[0] = '\0'; - if (!XGetTextProperty(dpy, w, &name, atom) || !name.nitems) - return 0; - if (name.encoding == XA_STRING) { - strncpy(text, (char *)name.value, size - 1); - } else if (XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) { - strncpy(text, *list, size - 1); - XFreeStringList(list); - } - text[size - 1] = '\0'; - XFree(name.value); - return 1; -} - -void -grabbuttons(Client *c, int focused) -{ - updatenumlockmask(); - { - unsigned int i, j; - unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; - XUngrabButton(dpy, AnyButton, AnyModifier, c->win); - if (!focused) - XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, - BUTTONMASK, GrabModeSync, GrabModeSync, None, None); - for (i = 0; i < LENGTH(buttons); i++) - if (buttons[i].click == ClkClientWin) - for (j = 0; j < LENGTH(modifiers); j++) - XGrabButton(dpy, buttons[i].button, - buttons[i].mask | modifiers[j], - c->win, False, BUTTONMASK, - GrabModeAsync, GrabModeSync, None, None); - } -} - -void -grabkeys(void) -{ - updatenumlockmask(); - { - unsigned int i, j, k; - unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; - int start, end, skip; - KeySym *syms; - - XUngrabKey(dpy, AnyKey, AnyModifier, root); - XDisplayKeycodes(dpy, &start, &end); - syms = XGetKeyboardMapping(dpy, start, end - start + 1, &skip); - if (!syms) - return; - for (k = start; k <= end; k++) - for (i = 0; i < LENGTH(keys); i++) - /* skip modifier codes, we do that ourselves */ - if (keys[i].keysym == syms[(k - start) * skip]) - for (j = 0; j < LENGTH(modifiers); j++) - XGrabKey(dpy, k, - keys[i].mod | modifiers[j], - root, True, - GrabModeAsync, GrabModeAsync); - XFree(syms); - } -} - -void -incnmaster(const Arg *arg) -{ - selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); - arrange(selmon); -} - -#ifdef XINERAMA -static int -isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) -{ - while (n--) - if (unique[n].x_org == info->x_org && unique[n].y_org == info->y_org - && unique[n].width == info->width && unique[n].height == info->height) - return 0; - return 1; -} -#endif /* XINERAMA */ - -void -keypress(XEvent *e) -{ - unsigned int i; - KeySym keysym; - XKeyEvent *ev; - - ev = &e->xkey; - keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); - for (i = 0; i < LENGTH(keys); i++) - if (keysym == keys[i].keysym - && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) - && keys[i].func) - keys[i].func(&(keys[i].arg)); -} - -void -killclient(const Arg *arg) -{ - if (!selmon->sel) - return; - if (!sendevent(selmon->sel, wmatom[WMDelete])) { - XGrabServer(dpy); - XSetErrorHandler(xerrordummy); - XSetCloseDownMode(dpy, DestroyAll); - XKillClient(dpy, selmon->sel->win); - XSync(dpy, False); - XSetErrorHandler(xerror); - XUngrabServer(dpy); - } -} - -void -manage(Window w, XWindowAttributes *wa) -{ - Client *c, *t = NULL; - Window trans = None; - XWindowChanges wc; - - c = ecalloc(1, sizeof(Client)); - c->win = w; - /* geometry */ - c->x = c->oldx = wa->x; - c->y = c->oldy = wa->y; - c->w = c->oldw = wa->width; - c->h = c->oldh = wa->height; - c->oldbw = wa->border_width; - - updatetitle(c); - if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { - c->mon = t->mon; - c->tags = t->tags; - } else { - c->mon = selmon; - applyrules(c); - } - - if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww) - c->x = c->mon->wx + c->mon->ww - WIDTH(c); - if (c->y + HEIGHT(c) > c->mon->wy + c->mon->wh) - c->y = c->mon->wy + c->mon->wh - HEIGHT(c); - c->x = MAX(c->x, c->mon->wx); - c->y = MAX(c->y, c->mon->wy); - c->bw = borderpx; - - wc.border_width = c->bw; - XConfigureWindow(dpy, w, CWBorderWidth, &wc); - XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); - configure(c); /* propagates border_width, if size doesn't change */ - updatewindowtype(c); - updatesizehints(c); - updatewmhints(c); - XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); - grabbuttons(c, 0); - if (!c->isfloating) - c->isfloating = c->oldstate = trans != None || c->isfixed; - if (c->isfloating) - XRaiseWindow(dpy, c->win); - attach(c); - attachstack(c); - XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, - (unsigned char *) &(c->win), 1); - XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ - setclientstate(c, NormalState); - if (c->mon == selmon) - unfocus(selmon->sel, 0); - c->mon->sel = c; - arrange(c->mon); - XMapWindow(dpy, c->win); - focus(NULL); -} - -void -mappingnotify(XEvent *e) -{ - XMappingEvent *ev = &e->xmapping; - - XRefreshKeyboardMapping(ev); - if (ev->request == MappingKeyboard) - grabkeys(); -} - -void -maprequest(XEvent *e) -{ - static XWindowAttributes wa; - XMapRequestEvent *ev = &e->xmaprequest; - - if (!XGetWindowAttributes(dpy, ev->window, &wa) || wa.override_redirect) - return; - if (!wintoclient(ev->window)) - manage(ev->window, &wa); -} - -void -monocle(Monitor *m) -{ - unsigned int n = 0; - Client *c; - - for (c = m->clients; c; c = c->next) - if (ISVISIBLE(c)) - n++; - if (n > 0) /* override layout symbol */ - snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n); - for (c = nexttiled(m->clients); c; c = nexttiled(c->next)) - resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0); -} - -void -motionnotify(XEvent *e) -{ - static Monitor *mon = NULL; - Monitor *m; - XMotionEvent *ev = &e->xmotion; - - if (ev->window != root) - return; - if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { - unfocus(selmon->sel, 1); - selmon = m; - focus(NULL); - } - mon = m; -} - -void -movemouse(const Arg *arg) -{ - int x, y, ocx, ocy, nx, ny; - Client *c; - Monitor *m; - XEvent ev; - Time lasttime = 0; - - if (!(c = selmon->sel)) - return; - if (c->isfullscreen) /* no support moving fullscreen windows by mouse */ - return; - restack(selmon); - ocx = c->x; - ocy = c->y; - if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, - None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) - return; - if (!getrootptr(&x, &y)) - return; - do { - XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); - switch(ev.type) { - case ConfigureRequest: - case Expose: - case MapRequest: - handler[ev.type](&ev); - break; - case MotionNotify: - if ((ev.xmotion.time - lasttime) <= (1000 / 60)) - continue; - lasttime = ev.xmotion.time; - - nx = ocx + (ev.xmotion.x - x); - ny = ocy + (ev.xmotion.y - y); - if (abs(selmon->wx - nx) < snap) - nx = selmon->wx; - else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap) - nx = selmon->wx + selmon->ww - WIDTH(c); - if (abs(selmon->wy - ny) < snap) - ny = selmon->wy; - else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap) - ny = selmon->wy + selmon->wh - HEIGHT(c); - if (!c->isfloating && selmon->lt[selmon->sellt]->arrange - && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) - togglefloating(NULL); - if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) - resize(c, nx, ny, c->w, c->h, 1); - break; - } - } while (ev.type != ButtonRelease); - XUngrabPointer(dpy, CurrentTime); - if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { - sendmon(c, m); - selmon = m; - focus(NULL); - } -} - -Client * -nexttiled(Client *c) -{ - for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); - return c; -} - -void -pop(Client *c) -{ - detach(c); - attach(c); - focus(c); - arrange(c->mon); -} - -void -propertynotify(XEvent *e) -{ - Client *c; - Window trans; - XPropertyEvent *ev = &e->xproperty; - - if ((ev->window == root) && (ev->atom == XA_WM_NAME)) - updatestatus(); - else if (ev->state == PropertyDelete) - return; /* ignore */ - else if ((c = wintoclient(ev->window))) { - switch(ev->atom) { - default: break; - case XA_WM_TRANSIENT_FOR: - if (!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) && - (c->isfloating = (wintoclient(trans)) != NULL)) - arrange(c->mon); - break; - case XA_WM_NORMAL_HINTS: - c->hintsvalid = 0; - break; - case XA_WM_HINTS: - updatewmhints(c); - drawbars(); - break; - } - if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { - updatetitle(c); - if (c == c->mon->sel) - drawbar(c->mon); - } - if (ev->atom == netatom[NetWMWindowType]) - updatewindowtype(c); - } -} - -void -quit(const Arg *arg) -{ - running = 0; -} - -void -quitprompt(const Arg *arg) -{ - FILE *pp = popen("echo -e \"no\nrestart\nyes\" | dmenu -i -sb red -p \"Quit DWM?\"", "r"); - if(pp != NULL) { - char buf[1024]; - if (fgets(buf, sizeof(buf), pp) == NULL) { - fprintf(stderr, "Quitprompt: Error reading pipe!\n"); - return; - } - if (strcmp(buf, "yes\n") == 0) { - pclose(pp); - restart = 0; - quit(NULL); - } else if (strcmp(buf, "restart\n") == 0) { - pclose(pp); - restart = 1; - quit(NULL); - } else if (strcmp(buf, "no\n") == 0) { - pclose(pp); - return; - } - } -} - -Monitor * -recttomon(int x, int y, int w, int h) -{ - Monitor *m, *r = selmon; - int a, area = 0; - - for (m = mons; m; m = m->next) - if ((a = INTERSECT(x, y, w, h, m)) > area) { - area = a; - r = m; - } - return r; -} - -void -resize(Client *c, int x, int y, int w, int h, int interact) -{ - if (applysizehints(c, &x, &y, &w, &h, interact)) - resizeclient(c, x, y, w, h); -} - -void -resizeclient(Client *c, int x, int y, int w, int h) -{ - XWindowChanges wc; - unsigned int n; - Client *nbc; - - c->oldx = c->x; c->x = wc.x = x; - c->oldy = c->y; c->y = wc.y = y; - c->oldw = c->w; c->w = wc.width = w; - c->oldh = c->h; c->h = wc.height = h; - wc.border_width = c->bw; - - for (n = 0, nbc = nexttiled(c->mon->clients); nbc; nbc = nexttiled(nbc->next), n++); - - if (c->isfloating || c->mon->lt[c->mon->sellt]->arrange == NULL) { - } else { - if (c->mon->lt[c->mon->sellt]->arrange == monocle || n == 1) { - wc.border_width = 0; - c->w = wc.width += c->bw * 2; - c->h = wc.height += c->bw * 2; - } - } - - XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); - configure(c); - XSync(dpy, False); -} - -void -resizemouse(const Arg *arg) -{ - int ocx, ocy, nw, nh; - Client *c; - Monitor *m; - XEvent ev; - Time lasttime = 0; - - if (!(c = selmon->sel)) - return; - if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ - return; - restack(selmon); - ocx = c->x; - ocy = c->y; - if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, - None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) - return; - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); - do { - XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); - switch(ev.type) { - case ConfigureRequest: - case Expose: - case MapRequest: - handler[ev.type](&ev); - break; - case MotionNotify: - if ((ev.xmotion.time - lasttime) <= (1000 / 60)) - continue; - lasttime = ev.xmotion.time; - - nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); - nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1); - if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww - && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh) - { - if (!c->isfloating && selmon->lt[selmon->sellt]->arrange - && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) - togglefloating(NULL); - } - if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) - resize(c, c->x, c->y, nw, nh, 1); - break; - } - } while (ev.type != ButtonRelease); - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); - XUngrabPointer(dpy, CurrentTime); - while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); - if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { - sendmon(c, m); - selmon = m; - focus(NULL); - } -} - -void -restack(Monitor *m) -{ - Client *c; - XEvent ev; - XWindowChanges wc; - - drawbar(m); - if (!m->sel) - return; - if (m->sel->isfloating || !m->lt[m->sellt]->arrange) - XRaiseWindow(dpy, m->sel->win); - if (m->lt[m->sellt]->arrange) { - wc.stack_mode = Below; - wc.sibling = m->barwin; - for (c = m->stack; c; c = c->snext) - if (!c->isfloating && ISVISIBLE(c)) { - XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); - wc.sibling = c->win; - } - } - if (m == selmon && (m->tagset[m->seltags] & m->sel->tags) && m->lt[m->sellt]->arrange != &monocle) - warp(m->sel); - XSync(dpy, False); - while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); -} - -void -run(void) -{ - XEvent ev; - /* main event loop */ - XSync(dpy, False); - while (running && !XNextEvent(dpy, &ev)) - if (handler[ev.type]) - handler[ev.type](&ev); /* call handler */ -} - -void -scan(void) -{ - unsigned int i, num; - Window d1, d2, *wins = NULL; - XWindowAttributes wa; - - if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { - for (i = 0; i < num; i++) { - if (!XGetWindowAttributes(dpy, wins[i], &wa) - || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) - continue; - if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) - manage(wins[i], &wa); - } - for (i = 0; i < num; i++) { /* now the transients */ - if (!XGetWindowAttributes(dpy, wins[i], &wa)) - continue; - if (XGetTransientForHint(dpy, wins[i], &d1) - && (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)) - manage(wins[i], &wa); - } - if (wins) - XFree(wins); - } -} - -void -selectclient(const Arg *_arg) -{ - static const char* dmenuwincmd[] = { "dmenu", "-i", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_purple, "-sf", col_gray4, NULL }; - Client *c; - int fds[4]; /* cin,sout,sin,cout */ - const char ln = '\n'; - char selected[257]; - int ret; - struct sigaction sa; - Arg arg; - - dmenumon[0] = '0' + selmon->num; - - if (pipe(fds)) - return; - if (pipe(fds+2)) { - close(fds[0]); - close(fds[1]); - return; - } - if (fork() == 0) { - close(fds[1]); - close(fds[2]); - dup2(fds[0], 0); - dup2(fds[3], 1); - - if (dpy) - close(ConnectionNumber(dpy)); - setsid(); - - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - sa.sa_handler = SIG_DFL; - sigaction(SIGCHLD, &sa, NULL); - - execvp(((char **)dmenuwincmd)[0], (char **)dmenuwincmd); - die("dwm: execvp 'dmenu' for window select failed:"); - } - close(fds[0]); - close(fds[3]); - - for (c = selmon->clients; c; c = c->next) { - write(fds[1], c->name, strlen(c->name)); - write(fds[1], &ln, 1); - } - close(fds[1]); - ret = read(fds[2], selected, 256); - for (int i = 0; i < 256 && (selected[i] != '\n' || (selected[i] = 0)); ++i); - close(fds[2]); - if (ret <= 0) - return; - for (c = selmon->clients; c; c = c->next) { - if (!strcmp(c->name, selected)) { - arg.ui = c->tags; - view(&arg); - focus(c); - return; - } - - } -} - -void -sendmon(Client *c, Monitor *m) -{ - if (c->mon == m) - return; - unfocus(c, 1); - detach(c); - detachstack(c); - c->mon = m; - c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ - attach(c); - attachstack(c); - focus(NULL); - arrange(NULL); -} - -void -setclientstate(Client *c, long state) -{ - long data[] = { state, None }; - - XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, - PropModeReplace, (unsigned char *)data, 2); -} - -int -sendevent(Client *c, Atom proto) -{ - int n; - Atom *protocols; - int exists = 0; - XEvent ev; - - if (XGetWMProtocols(dpy, c->win, &protocols, &n)) { - while (!exists && n--) - exists = protocols[n] == proto; - XFree(protocols); - } - if (exists) { - ev.type = ClientMessage; - ev.xclient.window = c->win; - ev.xclient.message_type = wmatom[WMProtocols]; - ev.xclient.format = 32; - ev.xclient.data.l[0] = proto; - ev.xclient.data.l[1] = CurrentTime; - XSendEvent(dpy, c->win, False, NoEventMask, &ev); - } - return exists; -} - -void -setfocus(Client *c) -{ - if (!c->neverfocus) { - XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); - XChangeProperty(dpy, root, netatom[NetActiveWindow], - XA_WINDOW, 32, PropModeReplace, - (unsigned char *) &(c->win), 1); - } - sendevent(c, wmatom[WMTakeFocus]); -} - -void -setfullscreen(Client *c, int fullscreen) -{ - if (fullscreen && !c->isfullscreen) { - XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, - PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); - c->isfullscreen = 1; - c->oldstate = c->isfloating; - c->oldbw = c->bw; - c->bw = 0; - c->isfloating = 1; - resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); - XRaiseWindow(dpy, c->win); - } else if (!fullscreen && c->isfullscreen){ - XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, - PropModeReplace, (unsigned char*)0, 0); - c->isfullscreen = 0; - c->isfloating = c->oldstate; - c->bw = c->oldbw; - c->x = c->oldx; - c->y = c->oldy; - c->w = c->oldw; - c->h = c->oldh; - resizeclient(c, c->x, c->y, c->w, c->h); - arrange(c->mon); - } -} - -void -setlayout(const Arg *arg) -{ - if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) - selmon->sellt ^= 1; - if (arg && arg->v) - selmon->lt[selmon->sellt] = (Layout *)arg->v; - strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); - if (selmon->sel) - arrange(selmon); - else - drawbar(selmon); -} - -/* arg > 1.0 will set mfact absolutely */ -void -setmfact(const Arg *arg) -{ - float f; - - if (!arg || !selmon->lt[selmon->sellt]->arrange) - return; - f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; - if (f < 0.05 || f > 0.95) - return; - selmon->mfact = f; - arrange(selmon); -} - -void -setup(void) -{ - int i; - XSetWindowAttributes wa; - Atom utf8string; - struct sigaction sa; - - /* do not transform children into zombies when they terminate */ - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_NOCLDSTOP | SA_NOCLDWAIT | SA_RESTART; - sa.sa_handler = SIG_IGN; - sigaction(SIGCHLD, &sa, NULL); - - /* clean up any zombies (inherited from .xinitrc etc) immediately */ - while (waitpid(-1, NULL, WNOHANG) > 0); - - /* init screen */ - screen = DefaultScreen(dpy); - sw = DisplayWidth(dpy, screen); - sh = DisplayHeight(dpy, screen); - root = RootWindow(dpy, screen); - drw = drw_create(dpy, screen, root, sw, sh); - if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) - die("no fonts could be loaded."); - lrpad = drw->fonts->h; - bh = drw->fonts->h + 2; - updategeom(); - /* init atoms */ - utf8string = XInternAtom(dpy, "UTF8_STRING", False); - wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); - wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); - wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); - wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); - netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); - netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); - netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); - netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); - netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); - netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); - netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); - netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); - netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); - /* init cursors */ - cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); - cursor[CurResize] = drw_cur_create(drw, XC_sizing); - cursor[CurMove] = drw_cur_create(drw, XC_fleur); - /* init appearance */ - scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); - for (i = 0; i < LENGTH(colors); i++) - scheme[i] = drw_scm_create(drw, colors[i], 3); - /* init bars */ - updatebars(); - updatestatus(); - /* supporting window for NetWMCheck */ - wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0); - XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32, - PropModeReplace, (unsigned char *) &wmcheckwin, 1); - XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8, - PropModeReplace, (unsigned char *) "dwm", 3); - XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32, - PropModeReplace, (unsigned char *) &wmcheckwin, 1); - /* EWMH support per view */ - XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, - PropModeReplace, (unsigned char *) netatom, NetLast); - XDeleteProperty(dpy, root, netatom[NetClientList]); - /* select events */ - wa.cursor = cursor[CurNormal]->cursor; - wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask - |ButtonPressMask|PointerMotionMask|EnterWindowMask - |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; - XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); - XSelectInput(dpy, root, wa.event_mask); - grabkeys(); - focus(NULL); -} - -void -seturgent(Client *c, int urg) -{ - XWMHints *wmh; - - c->isurgent = urg; - if (!(wmh = XGetWMHints(dpy, c->win))) - return; - wmh->flags = urg ? (wmh->flags | XUrgencyHint) : (wmh->flags & ~XUrgencyHint); - XSetWMHints(dpy, c->win, wmh); - XFree(wmh); -} - -void -showhide(Client *c) -{ - if (!c) - return; - if (ISVISIBLE(c)) { - /* show clients top down */ - XMoveWindow(dpy, c->win, c->x, c->y); - if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen) - resize(c, c->x, c->y, c->w, c->h, 0); - showhide(c->snext); - } else { - /* hide clients bottom up */ - showhide(c->snext); - XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y); - } -} - -void -spawn(const Arg *arg) -{ - struct sigaction sa; - - if (arg->v == dmenucmd) - dmenumon[0] = '0' + selmon->num; - if (fork() == 0) { - if (dpy) - close(ConnectionNumber(dpy)); - setsid(); - - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - sa.sa_handler = SIG_DFL; - sigaction(SIGCHLD, &sa, NULL); - - execvp(((char **)arg->v)[0], (char **)arg->v); - die("dwm: execvp '%s' failed:", ((char **)arg->v)[0]); - } -} - -void -tag(const Arg *arg) -{ - if (selmon->sel && arg->ui & TAGMASK) { - selmon->sel->tags = arg->ui & TAGMASK; - focus(NULL); - arrange(selmon); - } -} - -void -tagmon(const Arg *arg) -{ - if (!selmon->sel || !mons->next) - return; - sendmon(selmon->sel, dirtomon(arg->i)); -} - -void -tile(Monitor *m) -{ - unsigned int i, n, h, mw, my, ty; - Client *c; - - for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); - if (n == 0) - return; - - if (n > m->nmaster) - mw = m->nmaster ? m->ww * m->mfact : 0; - else - mw = m->ww; - for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) - if (i < m->nmaster) { - h = (m->wh - my) / (MIN(n, m->nmaster) - i); - resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); - if (my + HEIGHT(c) < m->wh) - my += HEIGHT(c); - } else { - h = (m->wh - ty) / (n - i); - resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); - if (ty + HEIGHT(c) < m->wh) - ty += HEIGHT(c); - } -} - -void -togglebar(const Arg *arg) -{ - selmon->showbar = !selmon->showbar; - updatebarpos(selmon); - XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); - arrange(selmon); -} - -void -togglefloating(const Arg *arg) -{ - if (!selmon->sel) - return; - if (selmon->sel->isfullscreen) /* no support for fullscreen windows */ - return; - selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; - if (selmon->sel->isfloating) - resize(selmon->sel, selmon->sel->x, selmon->sel->y, - selmon->sel->w, selmon->sel->h, 0); - arrange(selmon); -} - -void -toggletag(const Arg *arg) -{ - unsigned int newtags; - - if (!selmon->sel) - return; - newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); - if (newtags) { - selmon->sel->tags = newtags; - focus(NULL); - arrange(selmon); - } -} - -void -toggleview(const Arg *arg) -{ - unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); - - if (newtagset) { - selmon->tagset[selmon->seltags] = newtagset; - focus(NULL); - arrange(selmon); - } -} - -void -unfocus(Client *c, int setfocus) -{ - if (!c) - return; - grabbuttons(c, 0); - XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); - if (setfocus) { - XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); - XDeleteProperty(dpy, root, netatom[NetActiveWindow]); - } -} - -void -unmanage(Client *c, int destroyed) -{ - Monitor *m = c->mon; - XWindowChanges wc; - - detach(c); - detachstack(c); - if (!destroyed) { - wc.border_width = c->oldbw; - XGrabServer(dpy); /* avoid race conditions */ - XSetErrorHandler(xerrordummy); - XSelectInput(dpy, c->win, NoEventMask); - XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */ - XUngrabButton(dpy, AnyButton, AnyModifier, c->win); - setclientstate(c, WithdrawnState); - XSync(dpy, False); - XSetErrorHandler(xerror); - XUngrabServer(dpy); - } - free(c); - focus(NULL); - updateclientlist(); - arrange(m); -} - -void -unmapnotify(XEvent *e) -{ - Client *c; - XUnmapEvent *ev = &e->xunmap; - - if ((c = wintoclient(ev->window))) { - if (ev->send_event) - setclientstate(c, WithdrawnState); - else - unmanage(c, 0); - } -} - -void -updatebars(void) -{ - Monitor *m; - XSetWindowAttributes wa = { - .override_redirect = True, - .background_pixmap = ParentRelative, - .event_mask = ButtonPressMask|ExposureMask - }; - XClassHint ch = {"dwm", "dwm"}; - for (m = mons; m; m = m->next) { - if (m->barwin) - continue; - m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), - CopyFromParent, DefaultVisual(dpy, screen), - CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); - XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); - XMapRaised(dpy, m->barwin); - XSetClassHint(dpy, m->barwin, &ch); - } -} - -void -updatebarpos(Monitor *m) -{ - m->wy = m->my; - m->wh = m->mh; - if (m->showbar) { - m->wh -= bh; - m->by = m->topbar ? m->wy : m->wy + m->wh; - m->wy = m->topbar ? m->wy + bh : m->wy; - } else - m->by = -bh; -} - -void -updateclientlist(void) -{ - Client *c; - Monitor *m; - - XDeleteProperty(dpy, root, netatom[NetClientList]); - for (m = mons; m; m = m->next) - for (c = m->clients; c; c = c->next) - XChangeProperty(dpy, root, netatom[NetClientList], - XA_WINDOW, 32, PropModeAppend, - (unsigned char *) &(c->win), 1); -} - -int -updategeom(void) -{ - int dirty = 0; - -#ifdef XINERAMA - if (XineramaIsActive(dpy)) { - int i, j, n, nn; - Client *c; - Monitor *m; - XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); - XineramaScreenInfo *unique = NULL; - - for (n = 0, m = mons; m; m = m->next, n++); - /* only consider unique geometries as separate screens */ - unique = ecalloc(nn, sizeof(XineramaScreenInfo)); - for (i = 0, j = 0; i < nn; i++) - if (isuniquegeom(unique, j, &info[i])) - memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); - XFree(info); - nn = j; - - /* new monitors if nn > n */ - for (i = n; i < nn; i++) { - for (m = mons; m && m->next; m = m->next); - if (m) - m->next = createmon(); - else - mons = createmon(); - } - for (i = 0, m = mons; i < nn && m; m = m->next, i++) - if (i >= n - || unique[i].x_org != m->mx || unique[i].y_org != m->my - || unique[i].width != m->mw || unique[i].height != m->mh) - { - dirty = 1; - m->num = i; - m->mx = m->wx = unique[i].x_org; - m->my = m->wy = unique[i].y_org; - m->mw = m->ww = unique[i].width; - m->mh = m->wh = unique[i].height; - updatebarpos(m); - } - /* removed monitors if n > nn */ - for (i = nn; i < n; i++) { - for (m = mons; m && m->next; m = m->next); - while ((c = m->clients)) { - dirty = 1; - m->clients = c->next; - detachstack(c); - c->mon = mons; - attach(c); - attachstack(c); - } - if (m == selmon) - selmon = mons; - cleanupmon(m); - } - free(unique); - } else -#endif /* XINERAMA */ - { /* default monitor setup */ - if (!mons) - mons = createmon(); - if (mons->mw != sw || mons->mh != sh) { - dirty = 1; - mons->mw = mons->ww = sw; - mons->mh = mons->wh = sh; - updatebarpos(mons); - } - } - if (dirty) { - selmon = mons; - selmon = wintomon(root); - } - return dirty; -} - -void -updatenumlockmask(void) -{ - unsigned int i, j; - XModifierKeymap *modmap; - - numlockmask = 0; - modmap = XGetModifierMapping(dpy); - for (i = 0; i < 8; i++) - for (j = 0; j < modmap->max_keypermod; j++) - if (modmap->modifiermap[i * modmap->max_keypermod + j] - == XKeysymToKeycode(dpy, XK_Num_Lock)) - numlockmask = (1 << i); - XFreeModifiermap(modmap); -} - -void -updatesizehints(Client *c) -{ - long msize; - XSizeHints size; - - if (!XGetWMNormalHints(dpy, c->win, &size, &msize)) - /* size is uninitialized, ensure that size.flags aren't used */ - size.flags = PSize; - if (size.flags & PBaseSize) { - c->basew = size.base_width; - c->baseh = size.base_height; - } else if (size.flags & PMinSize) { - c->basew = size.min_width; - c->baseh = size.min_height; - } else - c->basew = c->baseh = 0; - if (size.flags & PResizeInc) { - c->incw = size.width_inc; - c->inch = size.height_inc; - } else - c->incw = c->inch = 0; - if (size.flags & PMaxSize) { - c->maxw = size.max_width; - c->maxh = size.max_height; - } else - c->maxw = c->maxh = 0; - if (size.flags & PMinSize) { - c->minw = size.min_width; - c->minh = size.min_height; - } else if (size.flags & PBaseSize) { - c->minw = size.base_width; - c->minh = size.base_height; - } else - c->minw = c->minh = 0; - if (size.flags & PAspect) { - c->mina = (float)size.min_aspect.y / size.min_aspect.x; - c->maxa = (float)size.max_aspect.x / size.max_aspect.y; - } else - c->maxa = c->mina = 0.0; - c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh); - c->hintsvalid = 1; -} - -void -updatestatus(void) -{ - if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) - strcpy(stext, "dwm-"VERSION); - drawbar(selmon); -} - -void -updatetitle(Client *c) -{ - if (!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name)) - gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name); - if (c->name[0] == '\0') /* hack to mark broken clients */ - strcpy(c->name, broken); -} - -void -updatewindowtype(Client *c) -{ - Atom state = getatomprop(c, netatom[NetWMState]); - Atom wtype = getatomprop(c, netatom[NetWMWindowType]); - - if (state == netatom[NetWMFullscreen]) - setfullscreen(c, 1); - if (wtype == netatom[NetWMWindowTypeDialog]) - c->isfloating = 1; -} - -void -updatewmhints(Client *c) -{ - XWMHints *wmh; - - if ((wmh = XGetWMHints(dpy, c->win))) { - if (c == selmon->sel && wmh->flags & XUrgencyHint) { - wmh->flags &= ~XUrgencyHint; - XSetWMHints(dpy, c->win, wmh); - } else - c->isurgent = (wmh->flags & XUrgencyHint) ? 1 : 0; - if (wmh->flags & InputHint) - c->neverfocus = !wmh->input; - else - c->neverfocus = 0; - XFree(wmh); - } -} - -void -view(const Arg *arg) -{ - if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) - return; - selmon->seltags ^= 1; /* toggle sel tagset */ - if (arg->ui & TAGMASK) - selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; - focus(NULL); - arrange(selmon); -} - -void -warp(const Client *c) -{ - int x, y; - - if (!c) { - XWarpPointer(dpy, None, root, 0, 0, 0, 0, selmon->wx + selmon->ww / 2, selmon->wy + selmon->wh / 2); - return; - } - - if (!getrootptr(&x, &y) || - (x > c->x - c->bw && - y > c->y - c->bw && - x < c->x + c->w + c->bw*2 && - y < c->y + c->h + c->bw*2) || - (y > c->mon->by && y < c->mon->by + bh) || - (c->mon->topbar && !y)) - return; - - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2); -} - -Client * -wintoclient(Window w) -{ - Client *c; - Monitor *m; - - for (m = mons; m; m = m->next) - for (c = m->clients; c; c = c->next) - if (c->win == w) - return c; - return NULL; -} - -Monitor * -wintomon(Window w) -{ - int x, y; - Client *c; - Monitor *m; - - if (w == root && getrootptr(&x, &y)) - return recttomon(x, y, 1, 1); - for (m = mons; m; m = m->next) - if (w == m->barwin) - return m; - if ((c = wintoclient(w))) - return c->mon; - return selmon; -} - -/* There's no way to check accesses to destroyed windows, thus those cases are - * ignored (especially on UnmapNotify's). Other types of errors call Xlibs - * default error handler, which may call exit. */ -int -xerror(Display *dpy, XErrorEvent *ee) -{ - if (ee->error_code == BadWindow - || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch) - || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable) - || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable) - || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable) - || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch) - || (ee->request_code == X_GrabButton && ee->error_code == BadAccess) - || (ee->request_code == X_GrabKey && ee->error_code == BadAccess) - || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable)) - return 0; - fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", - ee->request_code, ee->error_code); - return xerrorxlib(dpy, ee); /* may call exit */ -} - -int -xerrordummy(Display *dpy, XErrorEvent *ee) -{ - return 0; -} - -/* Startup Error handler to check if another window manager - * is already running. */ -int -xerrorstart(Display *dpy, XErrorEvent *ee) -{ - die("dwm: another window manager is already running"); - return -1; -} - -void -zoom(const Arg *arg) -{ - Client *c = selmon->sel; - - if (!selmon->lt[selmon->sellt]->arrange || !c || c->isfloating) - return; - if (c == nexttiled(selmon->clients) && !(c = nexttiled(c->next))) - return; - pop(c); -} - -int -main(int argc, char *argv[]) -{ - if (argc == 2 && !strcmp("-v", argv[1])) - die("dwm-"VERSION); - else if (argc != 1) - die("usage: dwm [-v]"); - if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) - fputs("warning: no locale support\n", stderr); - if (!(dpy = XOpenDisplay(NULL))) - die("dwm: cannot open display"); - checkotherwm(); - setup(); -#ifdef __OpenBSD__ - if (pledge("stdio rpath proc exec", NULL) == -1) - die("pledge"); -#endif /* __OpenBSD__ */ - scan(); - run(); - cleanup(); - XCloseDisplay(dpy); - if (restart == 1) { - execlp("dwm", "dwm", NULL); - } - return EXIT_SUCCESS; -} diff --git a/dwm/dwm-6.6/dwm.png b/dwm/dwm-6.6/dwm.png Binary files differdeleted file mode 100644 index b1f9ba7..0000000 --- a/dwm/dwm-6.6/dwm.png +++ /dev/null diff --git a/dwm/dwm-6.6/movestack.c b/dwm/dwm-6.6/movestack.c deleted file mode 100644 index c040462..0000000 --- a/dwm/dwm-6.6/movestack.c +++ /dev/null @@ -1,49 +0,0 @@ -void -movestack(const Arg *arg) { - Client *c = NULL, *p = NULL, *pc = NULL, *i; - - if(arg->i > 0) { - /* find the client after selmon->sel */ - for(c = selmon->sel->next; c && (!ISVISIBLE(c) || c->isfloating); c = c->next); - if(!c) - for(c = selmon->clients; c && (!ISVISIBLE(c) || c->isfloating); c = c->next); - - } - else { - /* find the client before selmon->sel */ - for(i = selmon->clients; i != selmon->sel; i = i->next) - if(ISVISIBLE(i) && !i->isfloating) - c = i; - if(!c) - for(; i; i = i->next) - if(ISVISIBLE(i) && !i->isfloating) - c = i; - } - /* find the client before selmon->sel and c */ - for(i = selmon->clients; i && (!p || !pc); i = i->next) { - if(i->next == selmon->sel) - p = i; - if(i->next == c) - pc = i; - } - - /* swap c and selmon->sel selmon->clients in the selmon->clients list */ - if(c && c != selmon->sel) { - Client *temp = selmon->sel->next==c?selmon->sel:selmon->sel->next; - selmon->sel->next = c->next==selmon->sel?c:c->next; - c->next = temp; - - if(p && p != c) - p->next = c; - if(pc && pc != selmon->sel) - pc->next = selmon->sel; - - if(selmon->sel == selmon->clients) - selmon->clients = c; - else if(c == selmon->clients) - selmon->clients = selmon->sel; - - arrange(selmon); - } -} - diff --git a/dwm/dwm-6.6/transient.c b/dwm/dwm-6.6/transient.c deleted file mode 100644 index 040adb5..0000000 --- a/dwm/dwm-6.6/transient.c +++ /dev/null @@ -1,42 +0,0 @@ -/* cc transient.c -o transient -lX11 */ - -#include <stdlib.h> -#include <unistd.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> - -int main(void) { - Display *d; - Window r, f, t = None; - XSizeHints h; - XEvent e; - - d = XOpenDisplay(NULL); - if (!d) - exit(1); - r = DefaultRootWindow(d); - - f = XCreateSimpleWindow(d, r, 100, 100, 400, 400, 0, 0, 0); - h.min_width = h.max_width = h.min_height = h.max_height = 400; - h.flags = PMinSize | PMaxSize; - XSetWMNormalHints(d, f, &h); - XStoreName(d, f, "floating"); - XMapWindow(d, f); - - XSelectInput(d, f, ExposureMask); - while (1) { - XNextEvent(d, &e); - - if (t == None) { - sleep(5); - t = XCreateSimpleWindow(d, r, 50, 50, 100, 100, 0, 0, 0); - XSetTransientForHint(d, t, f); - XStoreName(d, t, "transient"); - XMapWindow(d, t); - XSelectInput(d, t, ExposureMask); - } - } - - XCloseDisplay(d); - exit(0); -} diff --git a/dwm/dwm-6.6/util.c b/dwm/dwm-6.6/util.c deleted file mode 100644 index 8e26a51..0000000 --- a/dwm/dwm-6.6/util.c +++ /dev/null @@ -1,37 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <errno.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "util.h" - -void -die(const char *fmt, ...) -{ - va_list ap; - int saved_errno; - - saved_errno = errno; - - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - - if (fmt[0] && fmt[strlen(fmt)-1] == ':') - fprintf(stderr, " %s", strerror(saved_errno)); - fputc('\n', stderr); - - exit(1); -} - -void * -ecalloc(size_t nmemb, size_t size) -{ - void *p; - - if (!(p = calloc(nmemb, size))) - die("calloc:"); - return p; -} diff --git a/dwm/dwm-6.6/util.h b/dwm/dwm-6.6/util.h deleted file mode 100644 index c0a50d4..0000000 --- a/dwm/dwm-6.6/util.h +++ /dev/null @@ -1,9 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -#define MAX(A, B) ((A) > (B) ? (A) : (B)) -#define MIN(A, B) ((A) < (B) ? (A) : (B)) -#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) -#define LENGTH(X) (sizeof (X) / sizeof (X)[0]) - -void die(const char *fmt, ...); -void *ecalloc(size_t nmemb, size_t size); diff --git a/dwm/setup.sh b/dwm/setup.sh deleted file mode 100755 index 946011c..0000000 --- a/dwm/setup.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -set -e -set -x - -cd dwm-6.6 -rm -f config.h -make config.h -make install diff --git a/niceties/capslock/caps2esc b/niceties/capslock/caps2esc deleted file mode 100755 index ba0ed6f..0000000 --- a/niceties/capslock/caps2esc +++ /dev/null @@ -1,7 +0,0 @@ -#!/sbin/openrc-run - -name="caps2esc" -command="/usr/sbin/caps2escd" -command_background=true -pidfile="/run/caps2esc.pid" - diff --git a/niceties/capslock/caps2esc-tools b/niceties/capslock/caps2esc-tools deleted file mode 160000 -Subproject 6ad00311380254ce6c879f08456238c52b5f44c diff --git a/niceties/capslock/caps2escd b/niceties/capslock/caps2escd deleted file mode 100755 index 99539a4..0000000 --- a/niceties/capslock/caps2escd +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -# run udevmon with default settings -udevmon -c /etc/default/udevmon.yaml - diff --git a/niceties/capslock/interception-tools b/niceties/capslock/interception-tools deleted file mode 160000 -Subproject d1ac6116d4c28743f2931f0d94609c52de0149a diff --git a/niceties/capslock/udevmon.yaml b/niceties/capslock/udevmon.yaml deleted file mode 100644 index fd29ef6..0000000 --- a/niceties/capslock/udevmon.yaml +++ /dev/null @@ -1,6 +0,0 @@ -- JOB: - - intercept -g $DEVNODE | caps2esc -m 1 | uinput -d $DEVNODE - DEVICE: - #NAME: ".*((k|K)(eyboard|EYBOARD)|TADA68).*" - EVENTS: - EV_KEY: [KEY_CAPSLOCK, KEY_ESC] diff --git a/niceties/setup.sh b/niceties/setup.sh deleted file mode 100755 index 4692a40..0000000 --- a/niceties/setup.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -set -e -set -x - -sed -i -e 's_^PREFIX=.*$_PREFIX=${HOME}/.local_' unclutter-xfixes/Makefile - -cd unclutter-xfixes -make -make install -cd .. - -cd capslock -sudo ln -fs ${PWD}/udevmon.yaml /etc/default/udevmon.yaml -sudo ln -fs ${PWD}/caps2esc /etc/init.d/caps2esc -sudo ln -fs ${PWD}/caps2escd /usr/sbin/caps2escd -cd interception-tools -cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_POLICY_VERSION_MINIMUM=3.5 . -cmake --build build -sudo cmake --install build -cd ../caps2esc-tools -cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_POLICY_VERSION_MINIMUM=3.5 . -cmake --build build -sudo cmake --install build - diff --git a/niceties/unclutter-xfixes b/niceties/unclutter-xfixes deleted file mode 160000 -Subproject 0eb7a8f4365c05d09db048bd1a45f8943c1d5da diff --git a/brightness/brightnessdown b/scripts/brightness/brightnessdown index e48bd82..e48bd82 100755 --- a/brightness/brightnessdown +++ b/scripts/brightness/brightnessdown diff --git a/brightness/brightnessmax b/scripts/brightness/brightnessmax index d186f28..d186f28 100755 --- a/brightness/brightnessmax +++ b/scripts/brightness/brightnessmax diff --git a/brightness/brightnessup b/scripts/brightness/brightnessup index f1e3a40..f1e3a40 100755 --- a/brightness/brightnessup +++ b/scripts/brightness/brightnessup diff --git a/misc/lk.sh b/scripts/misc/lk.sh index 5f760c6..5f760c6 100755 --- a/misc/lk.sh +++ b/scripts/misc/lk.sh diff --git a/volume/volumedown b/scripts/volume/volumedown index aacc4fd..aacc4fd 100755 --- a/volume/volumedown +++ b/scripts/volume/volumedown diff --git a/volume/volumemute b/scripts/volume/volumemute index ac0f0d0..ac0f0d0 100755 --- a/volume/volumemute +++ b/scripts/volume/volumemute diff --git a/volume/volumeup b/scripts/volume/volumeup index 49d508e..49d508e 100755 --- a/volume/volumeup +++ b/scripts/volume/volumeup @@ -9,17 +9,38 @@ fi git submodule update --init --recursive -# handle files and symlinks -if [[ "$(read -e -p 'Check and install symlinks? [y/N]> '; echo $REPLY)" == [Yy]* ]]; then +confirm () { + [[ "$(read -e -p "$1 [y/N]> "; echo $REPLY)" == [Yy]* ]] +} + +if confirm "Check and install symlinks?"; then awk -f install.awk ensureddirs.csv symlinks.csv fi -# build various tools -if [[ "$(read -e -p 'Build dwm/st/slstatus? [y/N]> '; echo $REPLY)" == [Yy]* ]]; then +cd tree/src + +if confirm "Build and use tcc?"; then + cd tcc + ./setup.sh + cd .. + export CC=${HOME}/.local/bin/tcc +fi + +if confirm "Build micro haskell?"; then + cd microhs + ./setup.sh + cd .. +fi + +if confirm "Build dwm/st/slstatus/dmenu/unclutter?"; then cd dwm ./setup.sh cd .. + cd dmenu + ./setup.sh + cd .. + cd st ./setup.sh cd .. @@ -29,30 +50,15 @@ if [[ "$(read -e -p 'Build dwm/st/slstatus? [y/N]> '; echo $REPLY)" == [Yy]* ]]; cd .. fi -EMACSFULL="--with-x-toolkit=gtk3 --disable-build-details --with-cairo \ - --with-harfbuzz --with-libsystemd=no --with-modules \ - --with-tree-sitter" - -EMACSMIN="--without-all \ - --with-x-toolkit=no --without-xwidgets --without-x --without-ns --disable-ns-self-contained \ - --with-xpm=no --with-jpeg=no --with-png=no --with-gif=no --with-tiff=no \ - --without-internationalization --without-tree-sitter --without-mailutils" - -EMACSALWAYS="--with-gnutls --with-file-notification=yes --with-native-compilation=yes --with-zlib=yes" - -if [[ "$(read -e -p 'Build emacs? [y/N]> '; echo $REPLY)" == [Yy]* ]]; then - if [[ "$(read -e -p 'Build minimal emacs? [y/N]> '; echo $REPLY)" == [Yy]* ]]; then - EMACSOPT="${EMACSMIN} ${EMACSALWAYS}" - else - EMACSOPT="${EMACSFULL} ${EMACSALWAYS}" - fi - cd emacs-source - ./autogen.sh - ./configure --prefix="${HOME}/.local" \ - ${EMACSOPT} \ - CFLAGS='-O2 -pipe' - make - make install +if confirm "Build non-local tools (caps2esc) for openrc?"; then + cd capslock + ./setup.sh + cd .. +fi + +if confirm "Build Emacs?"; then + cd emacs + ./setup.sh cd .. fi diff --git a/slstatus/setup.sh b/slstatus/setup.sh deleted file mode 100755 index cf3367f..0000000 --- a/slstatus/setup.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -set -e -set -x - -cd slstatus-1.1 -rm -f config.h -make config.h -make install diff --git a/slstatus/slstatus-1.1.tar.gz b/slstatus/slstatus-1.1.tar.gz Binary files differdeleted file mode 100644 index 2ac5bfc..0000000 --- a/slstatus/slstatus-1.1.tar.gz +++ /dev/null diff --git a/slstatus/slstatus-1.1/LICENSE b/slstatus/slstatus-1.1/LICENSE deleted file mode 100644 index 9fae663..0000000 --- a/slstatus/slstatus-1.1/LICENSE +++ /dev/null @@ -1,46 +0,0 @@ -ISC License - -Copyright 2016-2025 Aaron Marcher <me@drkhsh.at> - -Copyright 2016 Roy Freytag <rfreytag@hs-mittweida.de> -Copyright 2016 Vincent Loupmon <vincentloupmon@gmail.com> -Copyright 2016 Daniel Walter <d.walter@0x90.at> -Copyright 2016-2018 Ali H. Fardan <raiz@firemail.cc> -Copyright 2016 Jody Leonard <me@jodyleonard.com> -Copyright 2016-2018 Quentin Rameau <quinq@fifth.space> -Copyright 2016 Mike Coddington <mike@coddington.us> -Copyright 2016-2018 Ivan J. <parazyd@dyne.org> -Copyright 2017 Tobias Stoeckmann <tobias@stoeckmann.org> -Copyright 2017-2018 Laslo Hunhold <dev@frign.de> -Copyright 2018 Darron Anderson <darronanderson@protonmail.com> -Copyright 2018 Josuah Demangeon <mail@josuah.net> -Copyright 2018 Tobias Tschinkowitz <tobias@he4d.net> -Copyright 2018 David Demelier <markand@malikania.fr> -Copyright 2018-2012 Michael Buch <michaelbuch12@gmail.com> -Copyright 2018 Ian Remmler <ian@remmler.org> -Copyright 2016-2019 Joerg Jung <jung@openbsd.org> -Copyright 2019 Ryan Kes <alrayyes@gmail.com> -Copyright 2019 Cem Keylan <cem@ckyln.com> -Copyright 2019 Dimitris Papastamos <dsp@2f30.org> -Copyright 2019-2022 Ingo Feinerer <feinerer@logic.at> -Copyright 2020 Alexandre Ratchov <alex@caoua.org> -Copyright 2020 Mart Lubbers <mart@martlubbers.net> -Copyright 2020 Daniel Moch <daniel@danielmoch.com> -Copyright 2022 Nickolas Raymond Kaczynski <nrk@disroot.org> -Copyright 2022 Patrick Iacob <iacobp@oregonstate.edu> -Copyright 2021-2022 Steven Ward <planet36@gmail.com> -Copyright 2025 Joakim Sindholt <opensource@zhasha.com> -Copyright 2025 Al <eirann@disroot.org> -Copyright 2025 sewn <sewn@disroot.org> - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/slstatus/slstatus-1.1/Makefile b/slstatus/slstatus-1.1/Makefile deleted file mode 100644 index 7a18274..0000000 --- a/slstatus/slstatus-1.1/Makefile +++ /dev/null @@ -1,69 +0,0 @@ -# See LICENSE file for copyright and license details -# slstatus - suckless status monitor -.POSIX: - -include config.mk - -REQ = util -COM =\ - components/battery\ - components/cat\ - components/cpu\ - components/datetime\ - components/disk\ - components/entropy\ - components/hostname\ - components/ip\ - components/kernel_release\ - components/keyboard_indicators\ - components/keymap\ - components/load_avg\ - components/netspeeds\ - components/num_files\ - components/ram\ - components/run_command\ - components/swap\ - components/temperature\ - components/uptime\ - components/user\ - components/volume\ - components/wifi - -all: slstatus - -$(COM:=.o): config.mk $(REQ:=.h) slstatus.h -slstatus.o: slstatus.c slstatus.h arg.h config.h config.mk $(REQ:=.h) - -.c.o: - $(CC) -o $@ -c $(CPPFLAGS) $(CFLAGS) $< - -config.h: - cp config.def.h $@ - -slstatus: slstatus.o $(COM:=.o) $(REQ:=.o) - $(CC) -o $@ $(LDFLAGS) $(COM:=.o) $(REQ:=.o) slstatus.o $(LDLIBS) - -clean: - rm -f slstatus slstatus.o $(COM:=.o) $(REQ:=.o) slstatus-${VERSION}.tar.gz - -dist: - rm -rf "slstatus-$(VERSION)" - mkdir -p "slstatus-$(VERSION)/components" - cp -R LICENSE Makefile README config.mk config.def.h \ - arg.h slstatus.h slstatus.c $(REQ:=.c) $(REQ:=.h) \ - slstatus.1 "slstatus-$(VERSION)" - cp -R $(COM:=.c) "slstatus-$(VERSION)/components" - tar -cf - "slstatus-$(VERSION)" | gzip -c > "slstatus-$(VERSION).tar.gz" - rm -rf "slstatus-$(VERSION)" - -install: all - mkdir -p "$(DESTDIR)$(PREFIX)/bin" - cp -f slstatus "$(DESTDIR)$(PREFIX)/bin" - chmod 755 "$(DESTDIR)$(PREFIX)/bin/slstatus" - mkdir -p "$(DESTDIR)$(MANPREFIX)/man1" - cp -f slstatus.1 "$(DESTDIR)$(MANPREFIX)/man1" - chmod 644 "$(DESTDIR)$(MANPREFIX)/man1/slstatus.1" - -uninstall: - rm -f "$(DESTDIR)$(PREFIX)/bin/slstatus" - rm -f "$(DESTDIR)$(MANPREFIX)/man1/slstatus.1" diff --git a/slstatus/slstatus-1.1/README b/slstatus/slstatus-1.1/README deleted file mode 100644 index 4d592bb..0000000 --- a/slstatus/slstatus-1.1/README +++ /dev/null @@ -1,65 +0,0 @@ -slstatus - suckless status -========================== -slstatus is a small tool for providing system status information to other -programs over the EWMH property of the root window (used by dwm(1)) or -standard input/output. It is designed to be as efficient as possible by -only issuing the minimum of system calls required. - - -Features --------- -- Battery percentage/state/time left -- Cat (read file) -- CPU usage -- CPU frequency -- Custom shell commands -- Date and time -- Disk status (free storage, percentage, total storage and used storage) -- Available entropy -- Username/GID/UID -- Hostname -- IP address (IPv4 and IPv6), interface status -- Kernel version -- Keyboard indicators -- Keymap -- Load average -- Network speeds (RX and TX) -- Number of files in a directory (hint: Maildir) -- Memory status (free memory, percentage, total memory and used memory) -- Swap status (free swap, percentage, total swap and used swap) -- Temperature -- Uptime -- Volume percentage -- WiFi signal percentage and ESSID - - -Requirements ------------- -Currently slstatus works on FreeBSD, Linux and OpenBSD. -In order to build slstatus you need the Xlib header files. - -- For volume percentage on Linux the kernel module `snd-mixer-oss` must be - loaded. -- For volume percentage on FreeBSD, `sndio` must be installed. - - -Installation ------------- -Edit config.mk to match your local setup (slstatus is installed into the -/usr/local namespace by default). - -Afterwards enter the following command to build and install slstatus (if -necessary as root): - - make clean install - - -Running slstatus ----------------- -See the man page for details. - - -Configuration -------------- -slstatus can be customized by creating a custom config.h and (re)compiling the -source code. This keeps it fast, secure and simple. diff --git a/slstatus/slstatus-1.1/arg.h b/slstatus/slstatus-1.1/arg.h deleted file mode 100644 index 5f1f408..0000000 --- a/slstatus/slstatus-1.1/arg.h +++ /dev/null @@ -1,33 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#ifndef ARG_H -#define ARG_H - -extern char *argv0; - -/* int main(int argc, char *argv[]) */ -#define ARGBEGIN for (argv0 = *argv, *argv ? (argc--, argv++) : ((void *)0); \ - *argv && (*argv)[0] == '-' && (*argv)[1]; argc--, argv++) { \ - int i_, argused_; \ - if ((*argv)[1] == '-' && !(*argv)[2]) { \ - argc--, argv++; \ - break; \ - } \ - for (i_ = 1, argused_ = 0; (*argv)[i_]; i_++) { \ - switch ((*argv)[i_]) -#define ARGEND if (argused_) { \ - if ((*argv)[i_ + 1]) { \ - break; \ - } else { \ - argc--, argv++; \ - break; \ - } \ - } \ - } \ - } -#define ARGC() ((*argv)[i_]) -#define ARGF_(x) (((*argv)[i_ + 1]) ? (argused_ = 1, &((*argv)[i_ + 1])) : \ - (*(argv + 1)) ? (argused_ = 1, *(argv + 1)) : (x)) -#define EARGF(x) ARGF_(((x), exit(1), (char *)0)) -#define ARGF() ARGF_((char *)0) - -#endif diff --git a/slstatus/slstatus-1.1/components/battery.c b/slstatus/slstatus-1.1/components/battery.c deleted file mode 100644 index 1c753f9..0000000 --- a/slstatus/slstatus-1.1/components/battery.c +++ /dev/null @@ -1,247 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <stdio.h> -#include <string.h> - -#include "../slstatus.h" -#include "../util.h" - -#if defined(__linux__) -/* - * https://www.kernel.org/doc/html/latest/power/power_supply_class.html - */ - #include <limits.h> - #include <stdint.h> - #include <unistd.h> - - #define POWER_SUPPLY_CAPACITY "/sys/class/power_supply/%s/capacity" - #define POWER_SUPPLY_STATUS "/sys/class/power_supply/%s/status" - #define POWER_SUPPLY_CHARGE "/sys/class/power_supply/%s/charge_now" - #define POWER_SUPPLY_ENERGY "/sys/class/power_supply/%s/energy_now" - #define POWER_SUPPLY_CURRENT "/sys/class/power_supply/%s/current_now" - #define POWER_SUPPLY_POWER "/sys/class/power_supply/%s/power_now" - - static const char * - pick(const char *bat, const char *f1, const char *f2, char *path, - size_t length) - { - if (esnprintf(path, length, f1, bat) > 0 && - access(path, R_OK) == 0) - return f1; - - if (esnprintf(path, length, f2, bat) > 0 && - access(path, R_OK) == 0) - return f2; - - return NULL; - } - - const char * - battery_perc(const char *bat) - { - int cap_perc; - char path[PATH_MAX]; - - if (esnprintf(path, sizeof(path), POWER_SUPPLY_CAPACITY, bat) < 0) - return NULL; - if (pscanf(path, "%d", &cap_perc) != 1) - return NULL; - - return bprintf("%d", cap_perc); - } - - const char * - battery_state(const char *bat) - { - static struct { - char *state; - char *symbol; - } map[] = { - { "Charging", "+" }, - { "Discharging", "-" }, - { "Full", "o" }, - { "Not charging", "o" }, - }; - size_t i; - char path[PATH_MAX], state[12]; - - if (esnprintf(path, sizeof(path), POWER_SUPPLY_STATUS, bat) < 0) - return NULL; - if (pscanf(path, "%12[a-zA-Z ]", state) != 1) - return NULL; - - for (i = 0; i < LEN(map); i++) - if (!strcmp(map[i].state, state)) - break; - - return (i == LEN(map)) ? "?" : map[i].symbol; - } - - const char * - battery_remaining(const char *bat) - { - uintmax_t charge_now, current_now, m, h; - double timeleft; - char path[PATH_MAX], state[12]; - - if (esnprintf(path, sizeof(path), POWER_SUPPLY_STATUS, bat) < 0) - return NULL; - if (pscanf(path, "%12[a-zA-Z ]", state) != 1) - return NULL; - - if (!pick(bat, POWER_SUPPLY_CHARGE, POWER_SUPPLY_ENERGY, path, - sizeof(path)) || - pscanf(path, "%ju", &charge_now) < 0) - return NULL; - - if (!strcmp(state, "Discharging")) { - if (!pick(bat, POWER_SUPPLY_CURRENT, POWER_SUPPLY_POWER, path, - sizeof(path)) || - pscanf(path, "%ju", ¤t_now) < 0) - return NULL; - - if (current_now == 0) - return NULL; - - timeleft = (double)charge_now / (double)current_now; - h = timeleft; - m = (timeleft - (double)h) * 60; - - return bprintf("%juh %jum", h, m); - } - - return ""; - } -#elif defined(__OpenBSD__) - #include <fcntl.h> - #include <machine/apmvar.h> - #include <sys/ioctl.h> - #include <unistd.h> - - static int - load_apm_power_info(struct apm_power_info *apm_info) - { - int fd; - - fd = open("/dev/apm", O_RDONLY); - if (fd < 0) { - warn("open '/dev/apm':"); - return 0; - } - - memset(apm_info, 0, sizeof(struct apm_power_info)); - if (ioctl(fd, APM_IOC_GETPOWER, apm_info) < 0) { - warn("ioctl 'APM_IOC_GETPOWER':"); - close(fd); - return 0; - } - return close(fd), 1; - } - - const char * - battery_perc(const char *unused) - { - struct apm_power_info apm_info; - - if (load_apm_power_info(&apm_info)) - return bprintf("%d", apm_info.battery_life); - - return NULL; - } - - const char * - battery_state(const char *unused) - { - struct { - unsigned int state; - char *symbol; - } map[] = { - { APM_AC_ON, "+" }, - { APM_AC_OFF, "-" }, - }; - struct apm_power_info apm_info; - size_t i; - - if (load_apm_power_info(&apm_info)) { - for (i = 0; i < LEN(map); i++) - if (map[i].state == apm_info.ac_state) - break; - - return (i == LEN(map)) ? "?" : map[i].symbol; - } - - return NULL; - } - - const char * - battery_remaining(const char *unused) - { - struct apm_power_info apm_info; - unsigned int h, m; - - if (load_apm_power_info(&apm_info)) { - if (apm_info.ac_state != APM_AC_ON) { - h = apm_info.minutes_left / 60; - m = apm_info.minutes_left % 60; - return bprintf("%uh %02um", h, m); - } else { - return ""; - } - } - - return NULL; - } -#elif defined(__FreeBSD__) - #include <sys/sysctl.h> - - #define BATTERY_LIFE "hw.acpi.battery.life" - #define BATTERY_STATE "hw.acpi.battery.state" - #define BATTERY_TIME "hw.acpi.battery.time" - - const char * - battery_perc(const char *unused) - { - int cap_perc; - size_t len; - - len = sizeof(cap_perc); - if (sysctlbyname(BATTERY_LIFE, &cap_perc, &len, NULL, 0) < 0 || !len) - return NULL; - - return bprintf("%d", cap_perc); - } - - const char * - battery_state(const char *unused) - { - int state; - size_t len; - - len = sizeof(state); - if (sysctlbyname(BATTERY_STATE, &state, &len, NULL, 0) < 0 || !len) - return NULL; - - switch (state) { - case 0: /* FALLTHROUGH */ - case 2: - return "+"; - case 1: - return "-"; - default: - return "?"; - } - } - - const char * - battery_remaining(const char *unused) - { - int rem; - size_t len; - - len = sizeof(rem); - if (sysctlbyname(BATTERY_TIME, &rem, &len, NULL, 0) < 0 || !len - || rem < 0) - return NULL; - - return bprintf("%uh %02um", rem / 60, rem % 60); - } -#endif diff --git a/slstatus/slstatus-1.1/components/cat.c b/slstatus/slstatus-1.1/components/cat.c deleted file mode 100644 index 07944cc..0000000 --- a/slstatus/slstatus-1.1/components/cat.c +++ /dev/null @@ -1,32 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <stdio.h> -#include <string.h> - -#include "../slstatus.h" -#include "../util.h" - -const char * -cat(const char *path) -{ - char *f; - FILE *fp; - - if (!(fp = fopen(path, "r"))) { - warn("fopen '%s':", path); - return NULL; - } - - f = fgets(buf, sizeof(buf) - 1, fp); - if (fclose(fp) < 0) { - warn("fclose '%s':", path); - return NULL; - } - if (!f) - return NULL; - - if ((f = strrchr(buf, '\n'))) - f[0] = '\0'; - - return buf[0] ? buf : NULL; -} - diff --git a/slstatus/slstatus-1.1/components/cpu.c b/slstatus/slstatus-1.1/components/cpu.c deleted file mode 100644 index d0d03c7..0000000 --- a/slstatus/slstatus-1.1/components/cpu.c +++ /dev/null @@ -1,157 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <stdint.h> -#include <stdio.h> -#include <string.h> - -#include "../slstatus.h" -#include "../util.h" - -#if defined(__linux__) - #define CPU_FREQ "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq" - - const char * - cpu_freq(const char *unused) - { - uintmax_t freq; - - /* in kHz */ - if (pscanf(CPU_FREQ, "%ju", &freq) != 1) - return NULL; - - return fmt_human(freq * 1000, 1000); - } - - const char * - cpu_perc(const char *unused) - { - static long double a[7]; - long double b[7], sum; - - memcpy(b, a, sizeof(b)); - /* cpu user nice system idle iowait irq softirq */ - if (pscanf("/proc/stat", "%*s %Lf %Lf %Lf %Lf %Lf %Lf %Lf", - &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6]) - != 7) - return NULL; - - if (b[0] == 0) - return NULL; - - sum = (b[0] + b[1] + b[2] + b[3] + b[4] + b[5] + b[6]) - - (a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6]); - - if (sum == 0) - return NULL; - - return bprintf("%d", (int)(100 * - ((b[0] + b[1] + b[2] + b[5] + b[6]) - - (a[0] + a[1] + a[2] + a[5] + a[6])) / sum)); - } -#elif defined(__OpenBSD__) - #include <sys/param.h> - #include <sys/sched.h> - #include <sys/sysctl.h> - - const char * - cpu_freq(const char *unused) - { - int freq, mib[2]; - size_t size; - - mib[0] = CTL_HW; - mib[1] = HW_CPUSPEED; - - size = sizeof(freq); - - /* in MHz */ - if (sysctl(mib, 2, &freq, &size, NULL, 0) < 0) { - warn("sysctl 'HW_CPUSPEED':"); - return NULL; - } - - return fmt_human(freq * 1E6, 1000); - } - - const char * - cpu_perc(const char *unused) - { - int mib[2]; - static uintmax_t a[CPUSTATES]; - uintmax_t b[CPUSTATES], sum; - size_t size; - - mib[0] = CTL_KERN; - mib[1] = KERN_CPTIME; - - size = sizeof(a); - - memcpy(b, a, sizeof(b)); - if (sysctl(mib, 2, &a, &size, NULL, 0) < 0) { - warn("sysctl 'KERN_CPTIME':"); - return NULL; - } - if (b[0] == 0) - return NULL; - - sum = (a[CP_USER] + a[CP_NICE] + a[CP_SYS] + a[CP_INTR] + a[CP_IDLE]) - - (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + b[CP_INTR] + b[CP_IDLE]); - - if (sum == 0) - return NULL; - - return bprintf("%d", 100 * - ((a[CP_USER] + a[CP_NICE] + a[CP_SYS] + - a[CP_INTR]) - - (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + - b[CP_INTR])) / sum); - } -#elif defined(__FreeBSD__) - #include <devstat.h> - #include <sys/param.h> - #include <sys/sysctl.h> - - const char * - cpu_freq(const char *unused) - { - int freq; - size_t size; - - size = sizeof(freq); - /* in MHz */ - if (sysctlbyname("hw.clockrate", &freq, &size, NULL, 0) < 0 || !size) { - warn("sysctlbyname 'hw.clockrate':"); - return NULL; - } - - return fmt_human(freq * 1E6, 1000); - } - - const char * - cpu_perc(const char *unused) - { - size_t size; - static long a[CPUSTATES]; - long b[CPUSTATES], sum; - - size = sizeof(a); - memcpy(b, a, sizeof(b)); - if (sysctlbyname("kern.cp_time", &a, &size, NULL, 0) < 0 || !size) { - warn("sysctlbyname 'kern.cp_time':"); - return NULL; - } - if (b[0] == 0) - return NULL; - - sum = (a[CP_USER] + a[CP_NICE] + a[CP_SYS] + a[CP_INTR] + a[CP_IDLE]) - - (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + b[CP_INTR] + b[CP_IDLE]); - - if (sum == 0) - return NULL; - - return bprintf("%d", 100 * - ((a[CP_USER] + a[CP_NICE] + a[CP_SYS] + - a[CP_INTR]) - - (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + - b[CP_INTR])) / sum); - } -#endif diff --git a/slstatus/slstatus-1.1/components/datetime.c b/slstatus/slstatus-1.1/components/datetime.c deleted file mode 100644 index 5b10daf..0000000 --- a/slstatus/slstatus-1.1/components/datetime.c +++ /dev/null @@ -1,20 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <stdio.h> -#include <time.h> - -#include "../slstatus.h" -#include "../util.h" - -const char * -datetime(const char *fmt) -{ - time_t t; - - t = time(NULL); - if (!strftime(buf, sizeof(buf), fmt, localtime(&t))) { - warn("strftime: Result string exceeds buffer size"); - return NULL; - } - - return buf; -} diff --git a/slstatus/slstatus-1.1/components/disk.c b/slstatus/slstatus-1.1/components/disk.c deleted file mode 100644 index e19a693..0000000 --- a/slstatus/slstatus-1.1/components/disk.c +++ /dev/null @@ -1,59 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <stdio.h> -#include <sys/statvfs.h> - -#include "../slstatus.h" -#include "../util.h" - -const char * -disk_free(const char *path) -{ - struct statvfs fs; - - if (statvfs(path, &fs) < 0) { - warn("statvfs '%s':", path); - return NULL; - } - - return fmt_human(fs.f_frsize * fs.f_bavail, 1024); -} - -const char * -disk_perc(const char *path) -{ - struct statvfs fs; - - if (statvfs(path, &fs) < 0) { - warn("statvfs '%s':", path); - return NULL; - } - - return bprintf("%d", (int)(100 * - (1 - ((double)fs.f_bavail / (double)fs.f_blocks)))); -} - -const char * -disk_total(const char *path) -{ - struct statvfs fs; - - if (statvfs(path, &fs) < 0) { - warn("statvfs '%s':", path); - return NULL; - } - - return fmt_human(fs.f_frsize * fs.f_blocks, 1024); -} - -const char * -disk_used(const char *path) -{ - struct statvfs fs; - - if (statvfs(path, &fs) < 0) { - warn("statvfs '%s':", path); - return NULL; - } - - return fmt_human(fs.f_frsize * (fs.f_blocks - fs.f_bfree), 1024); -} diff --git a/slstatus/slstatus-1.1/components/entropy.c b/slstatus/slstatus-1.1/components/entropy.c deleted file mode 100644 index 65010b0..0000000 --- a/slstatus/slstatus-1.1/components/entropy.c +++ /dev/null @@ -1,29 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "../slstatus.h" -#if defined(__linux__) - #include <stdint.h> - #include <stdio.h> - - #include "../util.h" - - #define ENTROPY_AVAIL "/proc/sys/kernel/random/entropy_avail" - - const char * - entropy(const char *unused) - { - uintmax_t num; - - if (pscanf(ENTROPY_AVAIL, "%ju", &num) != 1) - return NULL; - - return bprintf("%ju", num); - } -#elif defined(__OpenBSD__) | defined(__FreeBSD__) - const char * - entropy(const char *unused) - { - // https://www.unicode.org/charts/PDF/U2200.pdf - /* Unicode Character 'INFINITY' (U+221E) */ - return "\u221E"; - } -#endif diff --git a/slstatus/slstatus-1.1/components/hostname.c b/slstatus/slstatus-1.1/components/hostname.c deleted file mode 100644 index dab8b63..0000000 --- a/slstatus/slstatus-1.1/components/hostname.c +++ /dev/null @@ -1,17 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <stdio.h> -#include <unistd.h> - -#include "../slstatus.h" -#include "../util.h" - -const char * -hostname(const char *unused) -{ - if (gethostname(buf, sizeof(buf)) < 0) { - warn("gethostbyname:"); - return NULL; - } - - return buf; -} diff --git a/slstatus/slstatus-1.1/components/ip.c b/slstatus/slstatus-1.1/components/ip.c deleted file mode 100644 index 2cdad46..0000000 --- a/slstatus/slstatus-1.1/components/ip.c +++ /dev/null @@ -1,87 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <ifaddrs.h> -#include <netdb.h> -#include <net/if.h> -#include <stdio.h> -#include <string.h> -#if defined(__OpenBSD__) - #include <sys/socket.h> - #include <sys/types.h> -#elif defined(__FreeBSD__) - #include <netinet/in.h> - #include <sys/socket.h> -#endif - -#include "../slstatus.h" -#include "../util.h" - -static const char * -ip(const char *interface, unsigned short sa_family) -{ - struct ifaddrs *ifaddr, *ifa; - int s; - char host[NI_MAXHOST]; - - if (getifaddrs(&ifaddr) < 0) { - warn("getifaddrs:"); - return NULL; - } - - for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { - if (!ifa->ifa_addr) - continue; - - s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6), - host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); - if (!strcmp(ifa->ifa_name, interface) && - (ifa->ifa_addr->sa_family == sa_family)) { - freeifaddrs(ifaddr); - if (s != 0) { - warn("getnameinfo: %s", gai_strerror(s)); - return NULL; - } - return bprintf("%s", host); - } - } - - freeifaddrs(ifaddr); - - return NULL; -} - -const char * -ipv4(const char *interface) -{ - return ip(interface, AF_INET); -} - -const char * -ipv6(const char *interface) -{ - return ip(interface, AF_INET6); -} - -const char * -up(const char *interface) -{ - struct ifaddrs *ifaddr, *ifa; - - if (getifaddrs(&ifaddr) < 0) { - warn("getifaddrs:"); - return NULL; - } - - for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { - if (!ifa->ifa_addr) - continue; - - if (!strcmp(ifa->ifa_name, interface)) { - freeifaddrs(ifaddr); - return ifa->ifa_flags & IFF_UP ? "up" : "down"; - } - } - - freeifaddrs(ifaddr); - - return NULL; -} diff --git a/slstatus/slstatus-1.1/components/kernel_release.c b/slstatus/slstatus-1.1/components/kernel_release.c deleted file mode 100644 index 36a6a44..0000000 --- a/slstatus/slstatus-1.1/components/kernel_release.c +++ /dev/null @@ -1,19 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <stdio.h> -#include <sys/utsname.h> - -#include "../slstatus.h" -#include "../util.h" - -const char * -kernel_release(const char *unused) -{ - struct utsname udata; - - if (uname(&udata) < 0) { - warn("uname:"); - return NULL; - } - - return bprintf("%s", udata.release); -} diff --git a/slstatus/slstatus-1.1/components/keyboard_indicators.c b/slstatus/slstatus-1.1/components/keyboard_indicators.c deleted file mode 100644 index 5f62bb7..0000000 --- a/slstatus/slstatus-1.1/components/keyboard_indicators.c +++ /dev/null @@ -1,50 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <ctype.h> -#include <stdio.h> -#include <string.h> -#include <X11/Xlib.h> - -#include "../slstatus.h" -#include "../util.h" - -/* - * fmt consists of uppercase or lowercase 'c' for caps lock and/or 'n' for num - * lock, each optionally followed by '?', in the order of indicators desired. - * If followed by '?', the letter with case preserved is included in the output - * if the corresponding indicator is on. Otherwise, the letter is always - * included, lowercase when off and uppercase when on. - */ -const char * -keyboard_indicators(const char *fmt) -{ - Display *dpy; - XKeyboardState state; - size_t fmtlen, i, n; - int togglecase, isset; - char key; - - if (!(dpy = XOpenDisplay(NULL))) { - warn("XOpenDisplay: Failed to open display"); - return NULL; - } - XGetKeyboardControl(dpy, &state); - XCloseDisplay(dpy); - - fmtlen = strnlen(fmt, 4); - for (i = n = 0; i < fmtlen; i++) { - key = tolower(fmt[i]); - if (key != 'c' && key != 'n') - continue; - - togglecase = (i + 1 >= fmtlen || fmt[i + 1] != '?'); - isset = (state.led_mask & (1 << (key == 'n'))); - - if (togglecase) - buf[n++] = isset ? toupper(key) : key; - else if (isset) - buf[n++] = fmt[i]; - } - - buf[n] = 0; - return buf; -} diff --git a/slstatus/slstatus-1.1/components/keymap.c b/slstatus/slstatus-1.1/components/keymap.c deleted file mode 100644 index 22224f3..0000000 --- a/slstatus/slstatus-1.1/components/keymap.c +++ /dev/null @@ -1,86 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <ctype.h> -#include <stdlib.h> -#include <string.h> -#include <X11/XKBlib.h> -#include <X11/Xlib.h> - -#include "../slstatus.h" -#include "../util.h" - -static int -valid_layout_or_variant(char *sym) -{ - size_t i; - /* invalid symbols from xkb rules config */ - static const char *invalid[] = { "evdev", "inet", "pc", "base" }; - - for (i = 0; i < LEN(invalid); i++) - if (!strncmp(sym, invalid[i], strlen(invalid[i]))) - return 0; - - return 1; -} - -static char * -get_layout(char *syms, int grp_num) -{ - char *tok, *layout; - int grp; - - layout = NULL; - tok = strtok(syms, "+:_"); - for (grp = 0; tok && grp <= grp_num; tok = strtok(NULL, "+:_")) { - if (!valid_layout_or_variant(tok)) { - continue; - } else if (strlen(tok) == 1 && isdigit(tok[0])) { - /* ignore :2, :3, :4 (additional layout groups) */ - continue; - } - layout = tok; - grp++; - } - - return layout; -} - -const char * -keymap(const char *unused) -{ - Display *dpy; - XkbDescRec *desc; - XkbStateRec state; - char *symbols; - const char *layout; - - layout = NULL; - - if (!(dpy = XOpenDisplay(NULL))) { - warn("XOpenDisplay: Failed to open display"); - return NULL; - } - if (!(desc = XkbAllocKeyboard())) { - warn("XkbAllocKeyboard: Failed to allocate keyboard"); - goto end; - } - if (XkbGetNames(dpy, XkbSymbolsNameMask, desc)) { - warn("XkbGetNames: Failed to retrieve key symbols"); - goto end; - } - if (XkbGetState(dpy, XkbUseCoreKbd, &state)) { - warn("XkbGetState: Failed to retrieve keyboard state"); - goto end; - } - if (!(symbols = XGetAtomName(dpy, desc->names->symbols))) { - warn("XGetAtomName: Failed to get atom name"); - goto end; - } - layout = bprintf("%s", get_layout(symbols, state.group)); - XFree(symbols); -end: - XkbFreeKeyboard(desc, XkbSymbolsNameMask, 1); - if (XCloseDisplay(dpy)) - warn("XCloseDisplay: Failed to close display"); - - return layout; -} diff --git a/slstatus/slstatus-1.1/components/load_avg.c b/slstatus/slstatus-1.1/components/load_avg.c deleted file mode 100644 index f278a40..0000000 --- a/slstatus/slstatus-1.1/components/load_avg.c +++ /dev/null @@ -1,19 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <stdio.h> -#include <stdlib.h> - -#include "../slstatus.h" -#include "../util.h" - -const char * -load_avg(const char *unused) -{ - double avgs[3]; - - if (getloadavg(avgs, 3) < 0) { - warn("getloadavg: Failed to obtain load average"); - return NULL; - } - - return bprintf("%.2f %.2f %.2f", avgs[0], avgs[1], avgs[2]); -} diff --git a/slstatus/slstatus-1.1/components/netspeeds.c b/slstatus/slstatus-1.1/components/netspeeds.c deleted file mode 100644 index cde6fa9..0000000 --- a/slstatus/slstatus-1.1/components/netspeeds.c +++ /dev/null @@ -1,129 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <limits.h> -#include <stdio.h> - -#include "../slstatus.h" -#include "../util.h" - -#if defined(__linux__) - #include <stdint.h> - - #define NET_RX_BYTES "/sys/class/net/%s/statistics/rx_bytes" - #define NET_TX_BYTES "/sys/class/net/%s/statistics/tx_bytes" - - const char * - netspeed_rx(const char *interface) - { - uintmax_t oldrxbytes; - static uintmax_t rxbytes; - extern const unsigned int interval; - char path[PATH_MAX]; - - oldrxbytes = rxbytes; - - if (esnprintf(path, sizeof(path), NET_RX_BYTES, interface) < 0) - return NULL; - if (pscanf(path, "%ju", &rxbytes) != 1) - return NULL; - if (oldrxbytes == 0) - return NULL; - - return fmt_human((rxbytes - oldrxbytes) * 1000 / interval, - 1024); - } - - const char * - netspeed_tx(const char *interface) - { - uintmax_t oldtxbytes; - static uintmax_t txbytes; - extern const unsigned int interval; - char path[PATH_MAX]; - - oldtxbytes = txbytes; - - if (esnprintf(path, sizeof(path), NET_TX_BYTES, interface) < 0) - return NULL; - if (pscanf(path, "%ju", &txbytes) != 1) - return NULL; - if (oldtxbytes == 0) - return NULL; - - return fmt_human((txbytes - oldtxbytes) * 1000 / interval, - 1024); - } -#elif defined(__OpenBSD__) | defined(__FreeBSD__) - #include <ifaddrs.h> - #include <net/if.h> - #include <string.h> - #include <sys/types.h> - #include <sys/socket.h> - - const char * - netspeed_rx(const char *interface) - { - struct ifaddrs *ifal, *ifa; - struct if_data *ifd; - uintmax_t oldrxbytes; - static uintmax_t rxbytes; - extern const unsigned int interval; - int if_ok = 0; - - oldrxbytes = rxbytes; - - if (getifaddrs(&ifal) < 0) { - warn("getifaddrs failed"); - return NULL; - } - rxbytes = 0; - for (ifa = ifal; ifa; ifa = ifa->ifa_next) - if (!strcmp(ifa->ifa_name, interface) && - (ifd = (struct if_data *)ifa->ifa_data)) - rxbytes += ifd->ifi_ibytes, if_ok = 1; - - freeifaddrs(ifal); - if (!if_ok) { - warn("reading 'if_data' failed"); - return NULL; - } - if (oldrxbytes == 0) - return NULL; - - return fmt_human((rxbytes - oldrxbytes) * 1000 / interval, - 1024); - } - - const char * - netspeed_tx(const char *interface) - { - struct ifaddrs *ifal, *ifa; - struct if_data *ifd; - uintmax_t oldtxbytes; - static uintmax_t txbytes; - extern const unsigned int interval; - int if_ok = 0; - - oldtxbytes = txbytes; - - if (getifaddrs(&ifal) < 0) { - warn("getifaddrs failed"); - return NULL; - } - txbytes = 0; - for (ifa = ifal; ifa; ifa = ifa->ifa_next) - if (!strcmp(ifa->ifa_name, interface) && - (ifd = (struct if_data *)ifa->ifa_data)) - txbytes += ifd->ifi_obytes, if_ok = 1; - - freeifaddrs(ifal); - if (!if_ok) { - warn("reading 'if_data' failed"); - return NULL; - } - if (oldtxbytes == 0) - return NULL; - - return fmt_human((txbytes - oldtxbytes) * 1000 / interval, - 1024); - } -#endif diff --git a/slstatus/slstatus-1.1/components/num_files.c b/slstatus/slstatus-1.1/components/num_files.c deleted file mode 100644 index df0acd1..0000000 --- a/slstatus/slstatus-1.1/components/num_files.c +++ /dev/null @@ -1,32 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <dirent.h> -#include <stdio.h> -#include <string.h> - -#include "../slstatus.h" -#include "../util.h" - -const char * -num_files(const char *path) -{ - struct dirent *dp; - DIR *dir; - int num; - - if (!(dir = opendir(path))) { - warn("opendir '%s':", path); - return NULL; - } - - num = 0; - while ((dp = readdir(dir))) { - if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) - continue; /* skip self and parent */ - - num++; - } - - closedir(dir); - - return bprintf("%d", num); -} diff --git a/slstatus/slstatus-1.1/components/ram.c b/slstatus/slstatus-1.1/components/ram.c deleted file mode 100644 index 15c4b74..0000000 --- a/slstatus/slstatus-1.1/components/ram.c +++ /dev/null @@ -1,212 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <stdio.h> - -#include "../slstatus.h" -#include "../util.h" - -#if defined(__linux__) - #include <stdint.h> - - const char * - ram_free(const char *unused) - { - uintmax_t free; - - if (pscanf("/proc/meminfo", - "MemTotal: %ju kB\n" - "MemFree: %ju kB\n" - "MemAvailable: %ju kB\n", - &free, &free, &free) != 3) - return NULL; - - return fmt_human(free * 1024, 1024); - } - - const char * - ram_perc(const char *unused) - { - uintmax_t total, free, buffers, cached; - int percent; - - if (pscanf("/proc/meminfo", - "MemTotal: %ju kB\n" - "MemFree: %ju kB\n" - "MemAvailable: %ju kB\n" - "Buffers: %ju kB\n" - "Cached: %ju kB\n", - &total, &free, &buffers, &buffers, &cached) != 5) - return NULL; - - if (total == 0) - return NULL; - - percent = 100 * ((total - free) - (buffers + cached)) / total; - return bprintf("%d", percent); - } - - const char * - ram_total(const char *unused) - { - uintmax_t total; - - if (pscanf("/proc/meminfo", "MemTotal: %ju kB\n", &total) - != 1) - return NULL; - - return fmt_human(total * 1024, 1024); - } - - const char * - ram_used(const char *unused) - { - uintmax_t total, free, buffers, cached, used; - - if (pscanf("/proc/meminfo", - "MemTotal: %ju kB\n" - "MemFree: %ju kB\n" - "MemAvailable: %ju kB\n" - "Buffers: %ju kB\n" - "Cached: %ju kB\n", - &total, &free, &buffers, &buffers, &cached) != 5) - return NULL; - - used = (total - free - buffers - cached); - return fmt_human(used * 1024, 1024); - } -#elif defined(__OpenBSD__) - #include <stdlib.h> - #include <sys/sysctl.h> - #include <sys/types.h> - #include <unistd.h> - - #define LOG1024 10 - #define pagetok(size, pageshift) (size_t)(size << (pageshift - LOG1024)) - - inline int - load_uvmexp(struct uvmexp *uvmexp) - { - int uvmexp_mib[] = {CTL_VM, VM_UVMEXP}; - size_t size; - - size = sizeof(*uvmexp); - - if (sysctl(uvmexp_mib, 2, uvmexp, &size, NULL, 0) >= 0) - return 1; - - return 0; - } - - const char * - ram_free(const char *unused) - { - struct uvmexp uvmexp; - int free_pages; - - if (!load_uvmexp(&uvmexp)) - return NULL; - - free_pages = uvmexp.npages - uvmexp.active; - return fmt_human(pagetok(free_pages, uvmexp.pageshift) * - 1024, 1024); - } - - const char * - ram_perc(const char *unused) - { - struct uvmexp uvmexp; - int percent; - - if (!load_uvmexp(&uvmexp)) - return NULL; - - percent = uvmexp.active * 100 / uvmexp.npages; - return bprintf("%d", percent); - } - - const char * - ram_total(const char *unused) - { - struct uvmexp uvmexp; - - if (!load_uvmexp(&uvmexp)) - return NULL; - - return fmt_human(pagetok(uvmexp.npages, - uvmexp.pageshift) * 1024, 1024); - } - - const char * - ram_used(const char *unused) - { - struct uvmexp uvmexp; - - if (!load_uvmexp(&uvmexp)) - return NULL; - - return fmt_human(pagetok(uvmexp.active, - uvmexp.pageshift) * 1024, 1024); - } -#elif defined(__FreeBSD__) - #include <sys/sysctl.h> - #include <sys/vmmeter.h> - #include <unistd.h> - #include <vm/vm_param.h> - - const char * - ram_free(const char *unused) { - struct vmtotal vm_stats; - int mib[] = {CTL_VM, VM_TOTAL}; - size_t len; - - len = sizeof(struct vmtotal); - if (sysctl(mib, 2, &vm_stats, &len, NULL, 0) < 0 - || !len) - return NULL; - - return fmt_human(vm_stats.t_free * getpagesize(), 1024); - } - - const char * - ram_total(const char *unused) { - unsigned int npages; - size_t len; - - len = sizeof(npages); - if (sysctlbyname("vm.stats.vm.v_page_count", - &npages, &len, NULL, 0) < 0 || !len) - return NULL; - - return fmt_human(npages * getpagesize(), 1024); - } - - const char * - ram_perc(const char *unused) { - unsigned int npages; - unsigned int active; - size_t len; - - len = sizeof(npages); - if (sysctlbyname("vm.stats.vm.v_page_count", - &npages, &len, NULL, 0) < 0 || !len) - return NULL; - - if (sysctlbyname("vm.stats.vm.v_active_count", - &active, &len, NULL, 0) < 0 || !len) - return NULL; - - return bprintf("%d", active * 100 / npages); - } - - const char * - ram_used(const char *unused) { - unsigned int active; - size_t len; - - len = sizeof(active); - if (sysctlbyname("vm.stats.vm.v_active_count", - &active, &len, NULL, 0) < 0 || !len) - return NULL; - - return fmt_human(active * getpagesize(), 1024); - } -#endif diff --git a/slstatus/slstatus-1.1/components/run_command.c b/slstatus/slstatus-1.1/components/run_command.c deleted file mode 100644 index 93bf6da..0000000 --- a/slstatus/slstatus-1.1/components/run_command.c +++ /dev/null @@ -1,31 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <stdio.h> -#include <string.h> - -#include "../slstatus.h" -#include "../util.h" - -const char * -run_command(const char *cmd) -{ - char *p; - FILE *fp; - - if (!(fp = popen(cmd, "r"))) { - warn("popen '%s':", cmd); - return NULL; - } - - p = fgets(buf, sizeof(buf) - 1, fp); - if (pclose(fp) < 0) { - warn("pclose '%s':", cmd); - return NULL; - } - if (!p) - return NULL; - - if ((p = strrchr(buf, '\n'))) - p[0] = '\0'; - - return buf[0] ? buf : NULL; -} diff --git a/slstatus/slstatus-1.1/components/swap.c b/slstatus/slstatus-1.1/components/swap.c deleted file mode 100644 index f270d93..0000000 --- a/slstatus/slstatus-1.1/components/swap.c +++ /dev/null @@ -1,274 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "../slstatus.h" -#include "../util.h" - -#if defined(__linux__) - static int - get_swap_info(long *s_total, long *s_free, long *s_cached) - { - FILE *fp; - struct { - const char *name; - const size_t len; - long *var; - } ent[] = { - { "SwapTotal", sizeof("SwapTotal") - 1, s_total }, - { "SwapFree", sizeof("SwapFree") - 1, s_free }, - { "SwapCached", sizeof("SwapCached") - 1, s_cached }, - }; - size_t line_len = 0, i, left; - char *line = NULL; - - /* get number of fields we want to extract */ - for (i = 0, left = 0; i < LEN(ent); i++) - if (ent[i].var) - left++; - - if (!(fp = fopen("/proc/meminfo", "r"))) { - warn("fopen '/proc/meminfo':"); - return 1; - } - - /* read file line by line and extract field information */ - while (left > 0 && getline(&line, &line_len, fp) >= 0) { - for (i = 0; i < LEN(ent); i++) { - if (ent[i].var && - !strncmp(line, ent[i].name, ent[i].len)) { - sscanf(line + ent[i].len + 1, - "%ld kB\n", ent[i].var); - left--; - break; - } - } - } - free(line); - if (ferror(fp)) { - warn("getline '/proc/meminfo':"); - return 1; - } - - fclose(fp); - return 0; - } - - const char * - swap_free(const char *unused) - { - long free; - - if (get_swap_info(NULL, &free, NULL)) - return NULL; - - return fmt_human(free * 1024, 1024); - } - - const char * - swap_perc(const char *unused) - { - long total, free, cached; - - if (get_swap_info(&total, &free, &cached) || total == 0) - return NULL; - - return bprintf("%d", 100 * (total - free - cached) / total); - } - - const char * - swap_total(const char *unused) - { - long total; - - if (get_swap_info(&total, NULL, NULL)) - return NULL; - - return fmt_human(total * 1024, 1024); - } - - const char * - swap_used(const char *unused) - { - long total, free, cached; - - if (get_swap_info(&total, &free, &cached)) - return NULL; - - return fmt_human((total - free - cached) * 1024, 1024); - } -#elif defined(__OpenBSD__) - #include <stdlib.h> - #include <sys/swap.h> - #include <sys/types.h> - #include <unistd.h> - - static int - getstats(int *total, int *used) - { - struct swapent *sep, *fsep; - int rnswap, nswap, i; - - if ((nswap = swapctl(SWAP_NSWAP, 0, 0)) < 1) { - warn("swaptctl 'SWAP_NSWAP':"); - return 1; - } - if (!(fsep = sep = calloc(nswap, sizeof(*sep)))) { - warn("calloc 'nswap':"); - return 1; - } - if ((rnswap = swapctl(SWAP_STATS, (void *)sep, nswap)) < 0) { - warn("swapctl 'SWAP_STATA':"); - return 1; - } - if (nswap != rnswap) { - warn("getstats: SWAP_STATS != SWAP_NSWAP"); - return 1; - } - - *total = 0; - *used = 0; - - for (i = 0; i < rnswap; i++) { - *total += sep->se_nblks >> 1; - *used += sep->se_inuse >> 1; - } - - free(fsep); - - return 0; - } - - const char * - swap_free(const char *unused) - { - int total, used; - - if (getstats(&total, &used)) - return NULL; - - return fmt_human((total - used) * 1024, 1024); - } - - const char * - swap_perc(const char *unused) - { - int total, used; - - if (getstats(&total, &used)) - return NULL; - - if (total == 0) - return NULL; - - return bprintf("%d", 100 * used / total); - } - - const char * - swap_total(const char *unused) - { - int total, used; - - if (getstats(&total, &used)) - return NULL; - - return fmt_human(total * 1024, 1024); - } - - const char * - swap_used(const char *unused) - { - int total, used; - - if (getstats(&total, &used)) - return NULL; - - return fmt_human(used * 1024, 1024); - } -#elif defined(__FreeBSD__) - #include <fcntl.h> - #include <kvm.h> - #include <stdlib.h> - #include <sys/types.h> - #include <unistd.h> - - static int getswapinfo(struct kvm_swap *swap_info, size_t size) - { - kvm_t *kd; - - kd = kvm_openfiles(NULL, "/dev/null", NULL, 0, NULL); - if (kd == NULL) { - warn("kvm_openfiles '/dev/null':"); - return 0; - } - - if (kvm_getswapinfo(kd, swap_info, size, 0 /* Unused flags */) < 0) { - warn("kvm_getswapinfo:"); - kvm_close(kd); - return 0; - } - - kvm_close(kd); - return 1; - } - - const char * - swap_free(const char *unused) - { - struct kvm_swap swap_info[1]; - long used, total; - - if (!getswapinfo(swap_info, 1)) - return NULL; - - total = swap_info[0].ksw_total; - used = swap_info[0].ksw_used; - - return fmt_human((total - used) * getpagesize(), 1024); - } - - const char * - swap_perc(const char *unused) - { - struct kvm_swap swap_info[1]; - long used, total; - - if (!getswapinfo(swap_info, 1)) - return NULL; - - total = swap_info[0].ksw_total; - used = swap_info[0].ksw_used; - - return bprintf("%d", used * 100 / total); - } - - const char * - swap_total(const char *unused) - { - struct kvm_swap swap_info[1]; - long total; - - if (!getswapinfo(swap_info, 1)) - return NULL; - - total = swap_info[0].ksw_total; - - return fmt_human(total * getpagesize(), 1024); - } - - const char * - swap_used(const char *unused) - { - struct kvm_swap swap_info[1]; - long used; - - if (!getswapinfo(swap_info, 1)) - return NULL; - - used = swap_info[0].ksw_used; - - return fmt_human(used * getpagesize(), 1024); - } -#endif diff --git a/slstatus/slstatus-1.1/components/temperature.c b/slstatus/slstatus-1.1/components/temperature.c deleted file mode 100644 index 7cf1394..0000000 --- a/slstatus/slstatus-1.1/components/temperature.c +++ /dev/null @@ -1,73 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <stddef.h> - -#include "../slstatus.h" -#include "../util.h" - - -#if defined(__linux__) - #include <stdint.h> - - const char * - temp(const char *file) - { - uintmax_t temp; - - if (pscanf(file, "%ju", &temp) != 1) - return NULL; - - return bprintf("%ju", temp / 1000); - } -#elif defined(__OpenBSD__) - #include <stdio.h> - #include <sys/time.h> /* before <sys/sensors.h> for struct timeval */ - #include <sys/sensors.h> - #include <sys/sysctl.h> - - const char * - temp(const char *unused) - { - int mib[5]; - size_t size; - struct sensor temp; - - mib[0] = CTL_HW; - mib[1] = HW_SENSORS; - mib[2] = 0; /* cpu0 */ - mib[3] = SENSOR_TEMP; - mib[4] = 0; /* temp0 */ - - size = sizeof(temp); - - if (sysctl(mib, 5, &temp, &size, NULL, 0) < 0) { - warn("sysctl 'SENSOR_TEMP':"); - return NULL; - } - - /* kelvin to celsius */ - return bprintf("%d", (int)((float)(temp.value-273150000) / 1E6)); - } -#elif defined(__FreeBSD__) - #include <stdio.h> - #include <stdlib.h> - #include <sys/sysctl.h> - - #define ACPI_TEMP "hw.acpi.thermal.%s.temperature" - - const char * - temp(const char *zone) - { - char buf[256]; - int temp; - size_t len; - - len = sizeof(temp); - snprintf(buf, sizeof(buf), ACPI_TEMP, zone); - if (sysctlbyname(buf, &temp, &len, NULL, 0) < 0 - || !len) - return NULL; - - /* kelvin to decimal celcius */ - return bprintf("%d.%d", (temp - 2731) / 10, abs((temp - 2731) % 10)); - } -#endif diff --git a/slstatus/slstatus-1.1/components/uptime.c b/slstatus/slstatus-1.1/components/uptime.c deleted file mode 100644 index 6227f73..0000000 --- a/slstatus/slstatus-1.1/components/uptime.c +++ /dev/null @@ -1,34 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <stdint.h> -#include <stdio.h> -#include <time.h> - -#include "../slstatus.h" -#include "../util.h" - -#if defined(CLOCK_BOOTTIME) - #define UPTIME_FLAG CLOCK_BOOTTIME -#elif defined(CLOCK_UPTIME) - #define UPTIME_FLAG CLOCK_UPTIME -#else - #define UPTIME_FLAG CLOCK_MONOTONIC -#endif - -const char * -uptime(const char *unused) -{ - char warn_buf[256]; - uintmax_t h, m; - struct timespec uptime; - - if (clock_gettime(UPTIME_FLAG, &uptime) < 0) { - snprintf(warn_buf, sizeof(warn_buf), "clock_gettime %d", UPTIME_FLAG); - warn(warn_buf); - return NULL; - } - - h = uptime.tv_sec / 3600; - m = uptime.tv_sec % 3600 / 60; - - return bprintf("%juh %jum", h, m); -} diff --git a/slstatus/slstatus-1.1/components/user.c b/slstatus/slstatus-1.1/components/user.c deleted file mode 100644 index 3517495..0000000 --- a/slstatus/slstatus-1.1/components/user.c +++ /dev/null @@ -1,33 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <pwd.h> -#include <stdio.h> -#include <sys/types.h> -#include <unistd.h> - -#include "../slstatus.h" -#include "../util.h" - -const char * -gid(const char *unused) -{ - return bprintf("%d", getgid()); -} - -const char * -username(const char *unused) -{ - struct passwd *pw; - - if (!(pw = getpwuid(geteuid()))) { - warn("getpwuid '%d':", geteuid()); - return NULL; - } - - return bprintf("%s", pw->pw_name); -} - -const char * -uid(const char *unused) -{ - return bprintf("%d", geteuid()); -} diff --git a/slstatus/slstatus-1.1/components/volume.c b/slstatus/slstatus-1.1/components/volume.c deleted file mode 100644 index 6cec556..0000000 --- a/slstatus/slstatus-1.1/components/volume.c +++ /dev/null @@ -1,219 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <fcntl.h> -#include <stdio.h> -#include <string.h> -#include <sys/ioctl.h> -#include <unistd.h> - -#include "../slstatus.h" -#include "../util.h" - -#if defined(__OpenBSD__) | defined(__FreeBSD__) - #include <poll.h> - #include <sndio.h> - #include <stdlib.h> - #include <sys/queue.h> - - struct control { - LIST_ENTRY(control) next; - unsigned int addr; - #define CTRL_NONE 0 - #define CTRL_LEVEL 1 - #define CTRL_MUTE 2 - unsigned int type; - unsigned int maxval; - unsigned int val; - }; - - static LIST_HEAD(, control) controls = LIST_HEAD_INITIALIZER(controls); - static struct pollfd *pfds; - static struct sioctl_hdl *hdl; - static int initialized; - - /* - * Call-back to obtain the description of all audio controls. - */ - static void - ondesc(void *unused, struct sioctl_desc *desc, int val) - { - struct control *c, *ctmp; - unsigned int type = CTRL_NONE; - - if (desc == NULL) - return; - - /* Delete existing audio control with the same address. */ - LIST_FOREACH_SAFE(c, &controls, next, ctmp) { - if (desc->addr == c->addr) { - LIST_REMOVE(c, next); - free(c); - break; - } - } - - /* Only match output.level and output.mute audio controls. */ - if (desc->group[0] != 0 || - strcmp(desc->node0.name, "output") != 0) - return; - if (desc->type == SIOCTL_NUM && - strcmp(desc->func, "level") == 0) - type = CTRL_LEVEL; - else if (desc->type == SIOCTL_SW && - strcmp(desc->func, "mute") == 0) - type = CTRL_MUTE; - else - return; - - c = malloc(sizeof(struct control)); - if (c == NULL) { - warn("sndio: failed to allocate audio control\n"); - return; - } - - c->addr = desc->addr; - c->type = type; - c->maxval = desc->maxval; - c->val = val; - LIST_INSERT_HEAD(&controls, c, next); - } - - /* - * Call-back invoked whenever an audio control changes. - */ - static void - onval(void *unused, unsigned int addr, unsigned int val) - { - struct control *c; - - LIST_FOREACH(c, &controls, next) { - if (c->addr == addr) - break; - } - c->val = val; - } - - static void - cleanup(void) - { - struct control *c; - - if (hdl) { - sioctl_close(hdl); - hdl = NULL; - } - - free(pfds); - pfds = NULL; - - while (!LIST_EMPTY(&controls)) { - c = LIST_FIRST(&controls); - LIST_REMOVE(c, next); - free(c); - } - } - - static int - init(void) - { - hdl = sioctl_open(SIO_DEVANY, SIOCTL_READ, 0); - if (hdl == NULL) { - warn("sndio: cannot open device"); - goto failed; - } - - if (!sioctl_ondesc(hdl, ondesc, NULL)) { - warn("sndio: cannot set control description call-back"); - goto failed; - } - - if (!sioctl_onval(hdl, onval, NULL)) { - warn("sndio: cannot set control values call-back"); - goto failed; - } - - pfds = calloc(sioctl_nfds(hdl), sizeof(struct pollfd)); - if (pfds == NULL) { - warn("sndio: cannot allocate pollfd structures"); - goto failed; - } - - return 1; - failed: - cleanup(); - return 0; - } - - const char * - vol_perc(const char *unused) - { - struct control *c; - int n, v, value; - - if (!initialized) - initialized = init(); - - if (hdl == NULL) - return NULL; - - n = sioctl_pollfd(hdl, pfds, POLLIN); - if (n > 0) { - n = poll(pfds, n, 0); - if (n > 0) { - if (sioctl_revents(hdl, pfds) & POLLHUP) { - warn("sndio: disconnected"); - cleanup(); - initialized = 0; - return NULL; - } - } - } - - value = 100; - LIST_FOREACH(c, &controls, next) { - if (c->type == CTRL_MUTE && c->val == 1) - value = 0; - else if (c->type == CTRL_LEVEL) { - v = (c->val * 100 + c->maxval / 2) / c->maxval; - /* For multiple channels return the minimum. */ - if (v < value) - value = v; - } - } - - return bprintf("%d", value); - } -#else - #include <sys/soundcard.h> - - const char * - vol_perc(const char *card) - { - size_t i; - int v, afd, devmask; - char *vnames[] = SOUND_DEVICE_NAMES; - - if ((afd = open(card, O_RDONLY | O_NONBLOCK)) < 0) { - warn("open '%s':", card); - return NULL; - } - - if (ioctl(afd, (int)SOUND_MIXER_READ_DEVMASK, &devmask) < 0) { - warn("ioctl 'SOUND_MIXER_READ_DEVMASK':"); - close(afd); - return NULL; - } - for (i = 0; i < LEN(vnames); i++) { - if (devmask & (1 << i) && !strcmp("vol", vnames[i])) { - if (ioctl(afd, MIXER_READ(i), &v) < 0) { - warn("ioctl 'MIXER_READ(%ld)':", i); - close(afd); - return NULL; - } - } - } - - close(afd); - - return bprintf("%d", v & 0xff); - } -#endif diff --git a/slstatus/slstatus-1.1/components/wifi.c b/slstatus/slstatus-1.1/components/wifi.c deleted file mode 100644 index 23af201..0000000 --- a/slstatus/slstatus-1.1/components/wifi.c +++ /dev/null @@ -1,413 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <ifaddrs.h> -#include <stdio.h> -#include <string.h> -#include <sys/ioctl.h> -#include <sys/socket.h> -#include <unistd.h> - -#include "../slstatus.h" -#include "../util.h" - -#define RSSI_TO_PERC(rssi) \ - rssi >= -50 ? 100 : \ - (rssi <= -100 ? 0 : \ - (2 * (rssi + 100))) - -#if defined(__linux__) - #include <stdint.h> - #include <net/if.h> - #include <linux/netlink.h> - #include <linux/genetlink.h> - #include <linux/nl80211.h> - - static int nlsock = -1; - static uint32_t seq = 1; - static char resp[4096]; - - static char * - findattr(int attr, const char *p, const char *e, size_t *len) - { - while (p < e) { - struct nlattr nla; - memcpy(&nla, p, sizeof(nla)); - if (nla.nla_type == attr) { - *len = nla.nla_len - NLA_HDRLEN; - return (char *)(p + NLA_HDRLEN); - } - p += NLA_ALIGN(nla.nla_len); - } - return NULL; - } - - static uint16_t - nl80211fam(void) - { - static const char family[] = "nl80211"; - static uint16_t id; - ssize_t r; - size_t len; - char ctrl[NLMSG_HDRLEN+GENL_HDRLEN+NLA_HDRLEN+NLA_ALIGN(sizeof(family))] = {0}, *p = ctrl; - - if (id) - return id; - - memcpy(p, &(struct nlmsghdr){ - .nlmsg_len = sizeof(ctrl), - .nlmsg_type = GENL_ID_CTRL, - .nlmsg_flags = NLM_F_REQUEST, - .nlmsg_seq = seq++, - .nlmsg_pid = 0, - }, sizeof(struct nlmsghdr)); - p += NLMSG_HDRLEN; - memcpy(p, &(struct genlmsghdr){ - .cmd = CTRL_CMD_GETFAMILY, - .version = 1, - }, sizeof(struct genlmsghdr)); - p += GENL_HDRLEN; - memcpy(p, &(struct nlattr){ - .nla_len = NLA_HDRLEN+sizeof(family), - .nla_type = CTRL_ATTR_FAMILY_NAME, - }, sizeof(struct nlattr)); - p += NLA_HDRLEN; - memcpy(p, family, sizeof(family)); - - if (nlsock < 0) - nlsock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC); - if (nlsock < 0) { - warn("socket 'AF_NETLINK':"); - return 0; - } - if (send(nlsock, ctrl, sizeof(ctrl), 0) != sizeof(ctrl)) { - warn("send 'AF_NETLINK':"); - return 0; - } - r = recv(nlsock, resp, sizeof(resp), 0); - if (r < 0) { - warn("recv 'AF_NETLINK':"); - return 0; - } - if ((size_t)r <= sizeof(ctrl)) - return 0; - p = findattr(CTRL_ATTR_FAMILY_ID, resp + sizeof(ctrl), resp + r, &len); - if (p && len == 2) - memcpy(&id, p, 2); - - return id; - } - - static int - ifindex(const char *interface) - { - static struct ifreq ifr; - static int ifsock = -1; - - if (ifsock < 0) - ifsock = socket(AF_UNIX, SOCK_DGRAM, 0); - if (ifsock < 0) { - warn("socket 'AF_UNIX':"); - return -1; - } - if (strcmp(ifr.ifr_name, interface) != 0) { - strcpy(ifr.ifr_name, interface); - if (ioctl(ifsock, SIOCGIFINDEX, &ifr) != 0) { - warn("ioctl 'SIOCGIFINDEX':"); - return -1; - } - } - return ifr.ifr_ifindex; - } - - const char * - wifi_essid(const char *interface) - { - uint16_t fam = nl80211fam(); - ssize_t r; - size_t len; - char req[NLMSG_HDRLEN+GENL_HDRLEN+NLA_HDRLEN+NLA_ALIGN(4)] = {0}, *p = req; - int idx = ifindex(interface); - if (!fam) { - fprintf(stderr, "nl80211 family not found\n"); - return NULL; - } - if (idx < 0) { - fprintf(stderr, "interface %s not found\n", interface); - return NULL; - } - - memcpy(p, &(struct nlmsghdr){ - .nlmsg_len = sizeof(req), - .nlmsg_type = fam, - .nlmsg_flags = NLM_F_REQUEST, - .nlmsg_seq = seq++, - .nlmsg_pid = 0, - }, sizeof(struct nlmsghdr)); - p += NLMSG_HDRLEN; - memcpy(p, &(struct genlmsghdr){ - .cmd = NL80211_CMD_GET_INTERFACE, - .version = 1, - }, sizeof(struct genlmsghdr)); - p += GENL_HDRLEN; - memcpy(p, &(struct nlattr){ - .nla_len = NLA_HDRLEN+4, - .nla_type = NL80211_ATTR_IFINDEX, - }, sizeof(struct nlattr)); - p += NLA_HDRLEN; - memcpy(p, &(uint32_t){idx}, 4); - - if (send(nlsock, req, sizeof(req), 0) != sizeof(req)) { - warn("send 'AF_NETLINK':"); - return NULL; - } - r = recv(nlsock, resp, sizeof(resp), 0); - if (r < 0) { - warn("recv 'AF_NETLINK':"); - return NULL; - } - - if ((size_t)r <= NLMSG_HDRLEN + GENL_HDRLEN) - return NULL; - p = findattr(NL80211_ATTR_SSID, resp + NLMSG_HDRLEN + GENL_HDRLEN, resp + r, &len); - if (p) - p[len] = 0; - - return p; - } - - const char * - wifi_perc(const char *interface) - { - static char strength[4]; - struct nlmsghdr hdr; - uint16_t fam = nl80211fam(); - ssize_t r; - size_t len; - char req[NLMSG_HDRLEN + GENL_HDRLEN + NLA_HDRLEN + NLA_ALIGN(4)] = {0}, *p = req, *e; - int idx = ifindex(interface); - - if (idx < 0) { - fprintf(stderr, "interface %s not found\n", interface); - return NULL; - } - - memcpy(p, &(struct nlmsghdr){ - .nlmsg_len = sizeof(req), - .nlmsg_type = fam, - .nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP, - .nlmsg_seq = seq++, - .nlmsg_pid = 0, - }, sizeof(struct nlmsghdr)); - p += NLMSG_HDRLEN; - memcpy(p, &(struct genlmsghdr){ - .cmd = NL80211_CMD_GET_STATION, - .version = 1, - }, sizeof(struct genlmsghdr)); - p += GENL_HDRLEN; - memcpy(p, &(struct nlattr){ - .nla_len = NLA_HDRLEN + 4, - .nla_type = NL80211_ATTR_IFINDEX, - }, sizeof(struct nlattr)); - p += NLA_HDRLEN; - memcpy(p, &idx, 4); - - if (send(nlsock, req, sizeof(req), 0) != sizeof(req)) { - warn("send 'AF_NETLINK':"); - return NULL; - } - - *strength = 0; - while (1) { - r = recv(nlsock, resp, sizeof(resp), 0); - if (r < 0) { - warn("recv 'AF_NETLINK':"); - return NULL; - } - if ((size_t)r < sizeof(hdr)) - return NULL; - - for (p = resp; p != resp + r && (size_t)(resp + r-p) >= sizeof(hdr); p = e) { - memcpy(&hdr, p, sizeof(hdr)); - e = resp + r - p < hdr.nlmsg_len ? resp + r : p + hdr.nlmsg_len; - - if (!*strength && hdr.nlmsg_len > NLMSG_HDRLEN+GENL_HDRLEN) { - p += NLMSG_HDRLEN+GENL_HDRLEN; - p = findattr(NL80211_ATTR_STA_INFO, p, e, &len); - if (p) - p = findattr(NL80211_STA_INFO_SIGNAL_AVG, p, e, &len); - if (p && len == 1) - snprintf(strength, sizeof(strength), "%d", RSSI_TO_PERC(*p)); - } - if (hdr.nlmsg_type == NLMSG_DONE) - return *strength ? strength : NULL; - } - } - } -#elif defined(__OpenBSD__) - #include <net/if.h> - #include <net/if_media.h> - #include <net80211/ieee80211.h> - #include <sys/select.h> /* before <sys/ieee80211_ioctl.h> for NBBY */ - #include <net80211/ieee80211_ioctl.h> - #include <stdlib.h> - #include <sys/types.h> - - static int - load_ieee80211_nodereq(const char *interface, struct ieee80211_nodereq *nr) - { - struct ieee80211_bssid bssid; - int sockfd; - uint8_t zero_bssid[IEEE80211_ADDR_LEN]; - - memset(&bssid, 0, sizeof(bssid)); - memset(nr, 0, sizeof(struct ieee80211_nodereq)); - if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - warn("socket 'AF_INET':"); - return 0; - } - strlcpy(bssid.i_name, interface, sizeof(bssid.i_name)); - if ((ioctl(sockfd, SIOCG80211BSSID, &bssid)) < 0) { - warn("ioctl 'SIOCG80211BSSID':"); - close(sockfd); - return 0; - } - memset(&zero_bssid, 0, sizeof(zero_bssid)); - if (memcmp(bssid.i_bssid, zero_bssid, - IEEE80211_ADDR_LEN) == 0) { - close(sockfd); - return 0; - } - strlcpy(nr->nr_ifname, interface, sizeof(nr->nr_ifname)); - memcpy(&nr->nr_macaddr, bssid.i_bssid, sizeof(nr->nr_macaddr)); - if ((ioctl(sockfd, SIOCG80211NODE, nr)) < 0 && nr->nr_rssi) { - warn("ioctl 'SIOCG80211NODE':"); - close(sockfd); - return 0; - } - - return close(sockfd), 1; - } - - const char * - wifi_perc(const char *interface) - { - struct ieee80211_nodereq nr; - int q; - - if (load_ieee80211_nodereq(interface, &nr)) { - if (nr.nr_max_rssi) - q = IEEE80211_NODEREQ_RSSI(&nr); - else - q = RSSI_TO_PERC(nr.nr_rssi); - - return bprintf("%d", q); - } - - return NULL; - } - - const char * - wifi_essid(const char *interface) - { - struct ieee80211_nodereq nr; - - if (load_ieee80211_nodereq(interface, &nr)) - return bprintf("%s", nr.nr_nwid); - - return NULL; - } -#elif defined(__FreeBSD__) - #include <net/if.h> - #include <net80211/ieee80211_ioctl.h> - - int - load_ieee80211req(int sock, const char *interface, void *data, int type, size_t *len) - { - char warn_buf[256]; - struct ieee80211req ireq; - memset(&ireq, 0, sizeof(ireq)); - ireq.i_type = type; - ireq.i_data = (caddr_t) data; - ireq.i_len = *len; - - strlcpy(ireq.i_name, interface, sizeof(ireq.i_name)); - if (ioctl(sock, SIOCG80211, &ireq) < 0) { - snprintf(warn_buf, sizeof(warn_buf), - "ioctl: 'SIOCG80211': %d", type); - warn(warn_buf); - return 0; - } - - *len = ireq.i_len; - return 1; - } - - const char * - wifi_perc(const char *interface) - { - union { - struct ieee80211req_sta_req sta; - uint8_t buf[24 * 1024]; - } info; - uint8_t bssid[IEEE80211_ADDR_LEN]; - int rssi_dbm; - int sockfd; - size_t len; - const char *fmt; - - if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - warn("socket 'AF_INET':"); - return NULL; - } - - /* Retreive MAC address of interface */ - len = IEEE80211_ADDR_LEN; - fmt = NULL; - if (load_ieee80211req(sockfd, interface, &bssid, IEEE80211_IOC_BSSID, &len)) - { - /* Retrieve info on station with above BSSID */ - memset(&info, 0, sizeof(info)); - memcpy(info.sta.is_u.macaddr, bssid, sizeof(bssid)); - - len = sizeof(info); - if (load_ieee80211req(sockfd, interface, &info, IEEE80211_IOC_STA_INFO, &len)) { - rssi_dbm = info.sta.info[0].isi_noise + - info.sta.info[0].isi_rssi / 2; - - fmt = bprintf("%d", RSSI_TO_PERC(rssi_dbm)); - } - } - - close(sockfd); - return fmt; - } - - const char * - wifi_essid(const char *interface) - { - char ssid[IEEE80211_NWID_LEN + 1]; - size_t len; - int sockfd; - const char *fmt; - - if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - warn("socket 'AF_INET':"); - return NULL; - } - - fmt = NULL; - len = sizeof(ssid); - memset(&ssid, 0, len); - if (load_ieee80211req(sockfd, interface, &ssid, IEEE80211_IOC_SSID, &len)) { - if (len < sizeof(ssid)) - len += 1; - else - len = sizeof(ssid); - - ssid[len - 1] = '\0'; - fmt = bprintf("%s", ssid); - } - - close(sockfd); - return fmt; - } -#endif diff --git a/slstatus/slstatus-1.1/config.def.h b/slstatus/slstatus-1.1/config.def.h deleted file mode 100644 index 2a285cb..0000000 --- a/slstatus/slstatus-1.1/config.def.h +++ /dev/null @@ -1,74 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -/* interval between updates (in ms) */ -const unsigned int interval = 1000; - -/* text to show if no value can be retrieved */ -static const char unknown_str[] = "n/a"; - -/* maximum output string length */ -#define MAXLEN 2048 - -/* - * function description argument (example) - * - * battery_perc battery percentage battery name (BAT0) - * NULL on OpenBSD/FreeBSD - * battery_remaining battery remaining HH:MM battery name (BAT0) - * NULL on OpenBSD/FreeBSD - * battery_state battery charging state battery name (BAT0) - * NULL on OpenBSD/FreeBSD - * cat read arbitrary file path - * cpu_freq cpu frequency in MHz NULL - * cpu_perc cpu usage in percent NULL - * datetime date and time format string (%F %T) - * disk_free free disk space in GB mountpoint path (/) - * disk_perc disk usage in percent mountpoint path (/) - * disk_total total disk space in GB mountpoint path (/) - * disk_used used disk space in GB mountpoint path (/) - * entropy available entropy NULL - * gid GID of current user NULL - * hostname hostname NULL - * ipv4 IPv4 address interface name (eth0) - * ipv6 IPv6 address interface name (eth0) - * kernel_release `uname -r` NULL - * keyboard_indicators caps/num lock indicators format string (c?n?) - * see keyboard_indicators.c - * keymap layout (variant) of current NULL - * keymap - * load_avg load average NULL - * netspeed_rx receive network speed interface name (wlan0) - * netspeed_tx transfer network speed interface name (wlan0) - * num_files number of files in a directory path - * (/home/foo/Inbox/cur) - * ram_free free memory in GB NULL - * ram_perc memory usage in percent NULL - * ram_total total memory size in GB NULL - * ram_used used memory in GB NULL - * run_command custom shell command command (echo foo) - * swap_free free swap in GB NULL - * swap_perc swap usage in percent NULL - * swap_total total swap size in GB NULL - * swap_used used swap in GB NULL - * temp temperature in degree celsius sensor file - * (/sys/class/thermal/...) - * NULL on OpenBSD - * thermal zone on FreeBSD - * (tz0, tz1, etc.) - * uid UID of current user NULL - * up interface is running interface name (eth0) - * uptime system uptime NULL - * username username of current user NULL - * vol_perc OSS/ALSA volume in percent mixer file (/dev/mixer) - * NULL on OpenBSD/FreeBSD - * wifi_essid WiFi ESSID interface name (wlan0) - * wifi_perc WiFi signal in percent interface name (wlan0) - */ -static const struct arg args[] = { - /* function format argument */ - { battery_perc, "BAT: %s%% | ", "BAT0" }, - { cpu_perc, "CPU: %s%% | ", NULL }, - { ram_perc, "RAM: %s%% | ", NULL }, - { keymap, "KEY: %s | ", NULL }, - { datetime, "%s", "%F %T" }, -}; diff --git a/slstatus/slstatus-1.1/config.mk b/slstatus/slstatus-1.1/config.mk deleted file mode 100644 index 0de16de..0000000 --- a/slstatus/slstatus-1.1/config.mk +++ /dev/null @@ -1,22 +0,0 @@ -# slstatus version -VERSION = 1.1 - -# customize below to fit your system - -# paths -PREFIX = ${HOME}/.local -MANPREFIX = $(PREFIX)/share/man - -X11INC = /usr/X11R6/include -X11LIB = /usr/X11R6/lib - -# flags -CPPFLAGS = -I$(X11INC) -D_DEFAULT_SOURCE -DVERSION=\"${VERSION}\" -CFLAGS = -std=c99 -pedantic -Wall -Wextra -Wno-unused-parameter -Os -LDFLAGS = -L$(X11LIB) -s -# OpenBSD: add -lsndio -# FreeBSD: add -lkvm -lsndio -LDLIBS = -lX11 - -# compiler and linker -CC = cc diff --git a/slstatus/slstatus-1.1/slstatus.1 b/slstatus/slstatus-1.1/slstatus.1 deleted file mode 100644 index 73e7a60..0000000 --- a/slstatus/slstatus-1.1/slstatus.1 +++ /dev/null @@ -1,47 +0,0 @@ -.Dd 2023-04-23 -.Dt SLSTATUS 1 -.Os -.Sh NAME -.Nm slstatus -.Nd suckless status -.Sh SYNOPSIS -.Nm -.Op Fl s -.Op Fl 1 -.Sh DESCRIPTION -.Nm -is a small tool for providing system status information to other programs -over the EWMH -.Em WM_NAME -property of the root window (used by -.Xr dwm 1 ) or standard input/output. It is designed to be as efficient as possible by -only issuing the minimum of system calls required. -.P -By default, -.Nm -outputs to WM_NAME. -.Sh OPTIONS -.Bl -tag -width Ds -.It Fl v -Print version information to stderr, then exit. -.It Fl s -Write to stdout instead of WM_NAME. -.It Fl 1 -Write once to stdout and quit. -.El -.Sh CUSTOMIZATION -.Nm -can be customized by creating a custom config.h and (re)compiling the source -code. This keeps it fast, secure and simple. -.Sh SIGNALS -.Nm -responds to the following signals: -.Pp -.Bl -tag -width TERM -compact -.It USR1 -Triggers an instant redraw. -.El -.Sh AUTHORS -See the LICENSE file for the authors. -.Sh SEE ALSO -.Xr dwm 1 diff --git a/slstatus/slstatus-1.1/slstatus.c b/slstatus/slstatus-1.1/slstatus.c deleted file mode 100644 index 16d88fe..0000000 --- a/slstatus/slstatus-1.1/slstatus.c +++ /dev/null @@ -1,135 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <errno.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <X11/Xlib.h> - -#include "arg.h" -#include "slstatus.h" -#include "util.h" - -struct arg { - const char *(*func)(const char *); - const char *fmt; - const char *args; -}; - -char buf[1024]; -static volatile sig_atomic_t done; -static Display *dpy; - -#include "config.h" - -static void -terminate(const int signo) -{ - if (signo != SIGUSR1) - done = 1; -} - -static void -difftimespec(struct timespec *res, struct timespec *a, struct timespec *b) -{ - res->tv_sec = a->tv_sec - b->tv_sec - (a->tv_nsec < b->tv_nsec); - res->tv_nsec = a->tv_nsec - b->tv_nsec + - (a->tv_nsec < b->tv_nsec) * 1E9; -} - -static void -usage(void) -{ - die("usage: %s [-v] [-s] [-1]", argv0); -} - -int -main(int argc, char *argv[]) -{ - struct sigaction act; - struct timespec start, current, diff, intspec, wait; - size_t i, len; - int sflag, ret; - char status[MAXLEN]; - const char *res; - - sflag = 0; - ARGBEGIN { - case 'v': - die("slstatus-"VERSION); - break; - case '1': - done = 1; - /* FALLTHROUGH */ - case 's': - sflag = 1; - break; - default: - usage(); - } ARGEND - - if (argc) - usage(); - - memset(&act, 0, sizeof(act)); - act.sa_handler = terminate; - sigaction(SIGINT, &act, NULL); - sigaction(SIGTERM, &act, NULL); - act.sa_flags |= SA_RESTART; - sigaction(SIGUSR1, &act, NULL); - - if (!sflag && !(dpy = XOpenDisplay(NULL))) - die("XOpenDisplay: Failed to open display"); - - do { - if (clock_gettime(CLOCK_MONOTONIC, &start) < 0) - die("clock_gettime:"); - - status[0] = '\0'; - for (i = len = 0; i < LEN(args); i++) { - if (!(res = args[i].func(args[i].args))) - res = unknown_str; - - if ((ret = esnprintf(status + len, sizeof(status) - len, - args[i].fmt, res)) < 0) - break; - - len += ret; - } - - if (sflag) { - puts(status); - fflush(stdout); - if (ferror(stdout)) - die("puts:"); - } else { - if (XStoreName(dpy, DefaultRootWindow(dpy), status) < 0) - die("XStoreName: Allocation failed"); - XFlush(dpy); - } - - if (!done) { - if (clock_gettime(CLOCK_MONOTONIC, ¤t) < 0) - die("clock_gettime:"); - difftimespec(&diff, ¤t, &start); - - intspec.tv_sec = interval / 1000; - intspec.tv_nsec = (interval % 1000) * 1E6; - difftimespec(&wait, &intspec, &diff); - - if (wait.tv_sec >= 0 && - nanosleep(&wait, NULL) < 0 && - errno != EINTR) - die("nanosleep:"); - } - } while (!done); - - if (!sflag) { - XStoreName(dpy, DefaultRootWindow(dpy), NULL); - if (XCloseDisplay(dpy) < 0) - die("XCloseDisplay: Failed to close display"); - } - - return 0; -} diff --git a/slstatus/slstatus-1.1/slstatus.h b/slstatus/slstatus-1.1/slstatus.h deleted file mode 100644 index 394281c..0000000 --- a/slstatus/slstatus-1.1/slstatus.h +++ /dev/null @@ -1,85 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -/* battery */ -const char *battery_perc(const char *); -const char *battery_remaining(const char *); -const char *battery_state(const char *); - -/* cat */ -const char *cat(const char *path); - -/* cpu */ -const char *cpu_freq(const char *unused); -const char *cpu_perc(const char *unused); - -/* datetime */ -const char *datetime(const char *fmt); - -/* disk */ -const char *disk_free(const char *path); -const char *disk_perc(const char *path); -const char *disk_total(const char *path); -const char *disk_used(const char *path); - -/* entropy */ -const char *entropy(const char *unused); - -/* hostname */ -const char *hostname(const char *unused); - -/* ip */ -const char *ipv4(const char *interface); -const char *ipv6(const char *interface); -const char *up(const char *interface); - -/* kernel_release */ -const char *kernel_release(const char *unused); - -/* keyboard_indicators */ -const char *keyboard_indicators(const char *fmt); - -/* keymap */ -const char *keymap(const char *unused); - -/* load_avg */ -const char *load_avg(const char *unused); - -/* netspeeds */ -const char *netspeed_rx(const char *interface); -const char *netspeed_tx(const char *interface); - -/* num_files */ -const char *num_files(const char *path); - -/* ram */ -const char *ram_free(const char *unused); -const char *ram_perc(const char *unused); -const char *ram_total(const char *unused); -const char *ram_used(const char *unused); - -/* run_command */ -const char *run_command(const char *cmd); - -/* swap */ -const char *swap_free(const char *unused); -const char *swap_perc(const char *unused); -const char *swap_total(const char *unused); -const char *swap_used(const char *unused); - -/* temperature */ -const char *temp(const char *); - -/* uptime */ -const char *uptime(const char *unused); - -/* user */ -const char *gid(const char *unused); -const char *uid(const char *unused); -const char *username(const char *unused); - -/* volume */ -const char *vol_perc(const char *card); - -/* wifi */ -const char *wifi_essid(const char *interface); -const char *wifi_perc(const char *interface); diff --git a/slstatus/slstatus-1.1/util.c b/slstatus/slstatus-1.1/util.c deleted file mode 100644 index bca9b2e..0000000 --- a/slstatus/slstatus-1.1/util.c +++ /dev/null @@ -1,141 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <errno.h> -#include <stdarg.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "util.h" - -char *argv0; - -static void -verr(const char *fmt, va_list ap) -{ - vfprintf(stderr, fmt, ap); - - if (fmt[0] && fmt[strlen(fmt) - 1] == ':') { - fputc(' ', stderr); - perror(NULL); - } else { - fputc('\n', stderr); - } -} - -void -warn(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - verr(fmt, ap); - va_end(ap); -} - -void -die(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - verr(fmt, ap); - va_end(ap); - - exit(1); -} - -static int -evsnprintf(char *str, size_t size, const char *fmt, va_list ap) -{ - int ret; - - ret = vsnprintf(str, size, fmt, ap); - - if (ret < 0) { - warn("vsnprintf:"); - return -1; - } else if ((size_t)ret >= size) { - warn("vsnprintf: Output truncated"); - return -1; - } - - return ret; -} - -int -esnprintf(char *str, size_t size, const char *fmt, ...) -{ - va_list ap; - int ret; - - va_start(ap, fmt); - ret = evsnprintf(str, size, fmt, ap); - va_end(ap); - - return ret; -} - -const char * -bprintf(const char *fmt, ...) -{ - va_list ap; - int ret; - - va_start(ap, fmt); - ret = evsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - - return (ret < 0) ? NULL : buf; -} - -const char * -fmt_human(uintmax_t num, int base) -{ - double scaled; - size_t i, prefixlen; - const char **prefix; - const char *prefix_1000[] = { "", "k", "M", "G", "T", "P", "E", "Z", - "Y" }; - const char *prefix_1024[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", - "Zi", "Yi" }; - - switch (base) { - case 1000: - prefix = prefix_1000; - prefixlen = LEN(prefix_1000); - break; - case 1024: - prefix = prefix_1024; - prefixlen = LEN(prefix_1024); - break; - default: - warn("fmt_human: Invalid base"); - return NULL; - } - - scaled = num; - for (i = 0; i < prefixlen && scaled >= base; i++) - scaled /= base; - - return bprintf("%.1f %s", scaled, prefix[i]); -} - -int -pscanf(const char *path, const char *fmt, ...) -{ - FILE *fp; - va_list ap; - int n; - - if (!(fp = fopen(path, "r"))) { - warn("fopen '%s':", path); - return -1; - } - va_start(ap, fmt); - n = vfscanf(fp, fmt, ap); - va_end(ap); - fclose(fp); - - return (n == EOF) ? -1 : n; -} diff --git a/slstatus/slstatus-1.1/util.h b/slstatus/slstatus-1.1/util.h deleted file mode 100644 index cf4b027..0000000 --- a/slstatus/slstatus-1.1/util.h +++ /dev/null @@ -1,16 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <stdint.h> - -extern char buf[1024]; - -#define LEN(x) (sizeof(x) / sizeof((x)[0])) - -extern char *argv0; - -void warn(const char *, ...); -void die(const char *, ...); - -int esnprintf(char *str, size_t size, const char *fmt, ...); -const char *bprintf(const char *fmt, ...); -const char *fmt_human(uintmax_t num, int base); -int pscanf(const char *path, const char *fmt, ...); diff --git a/st/setup.sh b/st/setup.sh deleted file mode 100755 index db5296d..0000000 --- a/st/setup.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -set -e -set -x - -cd st-0.9.3 -rm -f config.h -make config.h -make install diff --git a/st/st-0.9.3.tar.gz b/st/st-0.9.3.tar.gz Binary files differdeleted file mode 100644 index ca8cd05..0000000 --- a/st/st-0.9.3.tar.gz +++ /dev/null diff --git a/st/st-0.9.3/FAQ b/st/st-0.9.3/FAQ deleted file mode 100644 index 6287a27..0000000 --- a/st/st-0.9.3/FAQ +++ /dev/null @@ -1,253 +0,0 @@ -## Why does st not handle utmp entries? - -Use the excellent tool of [utmp](https://git.suckless.org/utmp/) for this task. - - -## Some _random program_ complains that st is unknown/not recognised/unsupported/whatever! - -It means that st doesn’t have any terminfo entry on your system. Chances are -you did not `make install`. If you just want to test it without installing it, -you can manually run `tic -sx st.info`. - - -## Nothing works, and nothing is said about an unknown terminal! - -* Some programs just assume they’re running in xterm i.e. they don’t rely on - terminfo. What you see is the current state of the “xterm compliance”. -* Some programs don’t complain about the lacking st description and default to - another terminal. In that case see the question about terminfo. - - -## How do I scroll back up? - -* Using a terminal multiplexer. - * `st -e tmux` using C-b [ - * `st -e screen` using C-a ESC -* Using the excellent tool of [scroll](https://git.suckless.org/scroll/). -* Using the scrollback [patch](https://st.suckless.org/patches/scrollback/). - - -## I would like to have utmp and/or scroll functionality by default - -You can add the absolute path of both programs in your config.h file. You only -have to modify the value of utmp and scroll variables. - - -## Why doesn't the Del key work in some programs? - -Taken from the terminfo manpage: - - If the terminal has a keypad that transmits codes when the keys - are pressed, this information can be given. Note that it is not - possible to handle terminals where the keypad only works in - local (this applies, for example, to the unshifted HP 2621 keys). - If the keypad can be set to transmit or not transmit, give these - codes as smkx and rmkx. Otherwise the keypad is assumed to - always transmit. - -In the st case smkx=E[?1hE= and rmkx=E[?1lE>, so it is mandatory that -applications which want to test against keypad keys send these -sequences. - -But buggy applications (like bash and irssi, for example) don't do this. A fast -solution for them is to use the following command: - - $ printf '\033[?1h\033=' >/dev/tty - -or - $ tput smkx - -In the case of bash, readline is used. Readline has a different note in its -manpage about this issue: - - enable-keypad (Off) - When set to On, readline will try to enable the - application keypad when it is called. Some systems - need this to enable arrow keys. - -Adding this option to your .inputrc will fix the keypad problem for all -applications using readline. - -If you are using zsh, then read the zsh FAQ -<http://zsh.sourceforge.net/FAQ/zshfaq03.html#l25>: - - It should be noted that the O / [ confusion can occur with other keys - such as Home and End. Some systems let you query the key sequences - sent by these keys from the system's terminal database, terminfo. - Unfortunately, the key sequences given there typically apply to the - mode that is not the one zsh uses by default (it's the "application" - mode rather than the "raw" mode). Explaining the use of terminfo is - outside of the scope of this FAQ, but if you wish to use the key - sequences given there you can tell the line editor to turn on - "application" mode when it starts and turn it off when it stops: - - function zle-line-init () { echoti smkx } - function zle-line-finish () { echoti rmkx } - zle -N zle-line-init - zle -N zle-line-finish - -Putting these lines into your .zshrc will fix the problems. - - -## How can I use meta in 8bit mode? - -St supports meta in 8bit mode, but the default terminfo entry doesn't -use this capability. If you want it, you have to use the 'st-meta' value -in TERM. - - -## I cannot compile st in OpenBSD - -OpenBSD lacks librt, despite it being mandatory in POSIX -<http://pubs.opengroup.org/onlinepubs/9699919799/utilities/c99.html#tag_20_11_13>. -If you want to compile st for OpenBSD you have to remove -lrt from config.mk, and -st will compile without any loss of functionality, because all the functions are -included in libc on this platform. - - -## The Backspace Case - -St is emulating the Linux way of handling backspace being delete and delete being -backspace. - -This is an issue that was discussed in suckless mailing list -<https://lists.suckless.org/dev/1404/20697.html>. Here is why some old grumpy -terminal users wants its backspace to be how he feels it: - - Well, I am going to comment why I want to change the behaviour - of this key. When ASCII was defined in 1968, communication - with computers was done using punched cards, or hardcopy - terminals (basically a typewriter machine connected with the - computer using a serial port). ASCII defines DELETE as 7F, - because, in punched-card terms, it means all the holes of the - card punched; it is thus a kind of 'physical delete'. In the - same way, the BACKSPACE key was a non-destructive backspace, - as on a typewriter. So, if you wanted to delete a character, - you had to BACKSPACE and then DELETE. Another use of BACKSPACE - was to type accented characters, for example 'a BACKSPACE `'. - The VT100 had no BACKSPACE key; it was generated using the - CONTROL key as another control character (CONTROL key sets to - 0 b7 b6 b5, so it converts H (code 0x48) into BACKSPACE (code - 0x08)), but it had a DELETE key in a similar position where - the BACKSPACE key is located today on common PC keyboards. - All the terminal emulators emulated the difference between - these keys correctly: the backspace key generated a BACKSPACE - (^H) and delete key generated a DELETE (^?). - - But a problem arose when Linus Torvalds wrote Linux. Unlike - earlier terminals, the Linux virtual terminal (the terminal - emulator integrated in the kernel) returned a DELETE when - backspace was pressed, due to the VT100 having a DELETE key in - the same position. This created a lot of problems (see [1] - and [2]). Since Linux has become the king, a lot of terminal - emulators today generate a DELETE when the backspace key is - pressed in order to avoid problems with Linux. The result is - that the only way of generating a BACKSPACE on these systems - is by using CONTROL + H. (I also think that emacs had an - important point here because the CONTROL + H prefix is used - in emacs in some commands (help commands).) - - From point of view of the kernel, you can change the key - for deleting a previous character with stty erase. When you - connect a real terminal into a machine you describe the type - of terminal, so getty configures the correct value of stty - erase for this terminal. In the case of terminal emulators, - however, you don't have any getty that can set the correct - value of stty erase, so you always get the default value. - For this reason, it is necessary to add 'stty erase ^H' to your - profile if you have changed the value of the backspace key. - Of course, another solution is for st itself to modify the - value of stty erase. I usually have the inverse problem: - when I connect to non-Unix machines, I have to press CONTROL + - h to get a BACKSPACE. The inverse problem occurs when a user - connects to my Unix machines from a different system with a - correct backspace key. - - [1] http://www.ibb.net/~anne/keyboard.html - [2] http://www.tldp.org/HOWTO/Keyboard-and-Console-HOWTO-5.html - - -## But I really want the old grumpy behaviour of my terminal - -Apply [1]. - -[1] https://st.suckless.org/patches/delkey - - -## Why do images not work in st using the w3m image hack? - -w3mimg uses a hack that draws an image on top of the terminal emulator Drawable -window. The hack relies on the terminal to use a single buffer to draw its -contents directly. - -st uses double-buffered drawing so the image is quickly replaced and may show a -short flicker effect. - -Below is a patch example to change st double-buffering to a single Drawable -buffer. - -diff --git a/x.c b/x.c ---- a/x.c -+++ b/x.c -@@ -732,10 +732,6 @@ xresize(int col, int row) - win.tw = col * win.cw; - win.th = row * win.ch; - -- XFreePixmap(xw.dpy, xw.buf); -- xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, -- DefaultDepth(xw.dpy, xw.scr)); -- XftDrawChange(xw.draw, xw.buf); - xclear(0, 0, win.w, win.h); - - /* resize to new width */ -@@ -1148,8 +1144,7 @@ xinit(int cols, int rows) - gcvalues.graphics_exposures = False; - dc.gc = XCreateGC(xw.dpy, parent, GCGraphicsExposures, - &gcvalues); -- xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, -- DefaultDepth(xw.dpy, xw.scr)); -+ xw.buf = xw.win; - XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); - XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); - -@@ -1632,8 +1627,6 @@ xdrawline(Line line, int x1, int y1, int x2) - void - xfinishdraw(void) - { -- XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w, -- win.h, 0, 0); - XSetForeground(xw.dpy, dc.gc, - dc.col[IS_SET(MODE_REVERSE)? - defaultfg : defaultbg].pixel); - - -## BadLength X error in Xft when trying to render emoji - -Xft makes st crash when rendering color emojis with the following error: - -"X Error of failed request: BadLength (poly request too large or internal Xlib length error)" - Major opcode of failed request: 139 (RENDER) - Minor opcode of failed request: 20 (RenderAddGlyphs) - Serial number of failed request: 1595 - Current serial number in output stream: 1818" - -This is a known bug in Xft (not st) which happens on some platforms and -combination of particular fonts and fontconfig settings. - -See also: -https://gitlab.freedesktop.org/xorg/lib/libxft/issues/6 -https://bugs.freedesktop.org/show_bug.cgi?id=107534 -https://bugzilla.redhat.com/show_bug.cgi?id=1498269 - -The solution is to remove color emoji fonts or disable this in the fontconfig -XML configuration. As an ugly workaround (which may work only on newer -fontconfig versions (FC_COLOR)), the following code can be used to mask color -fonts: - - FcPatternAddBool(fcpattern, FC_COLOR, FcFalse); - -Please don't bother reporting this bug to st, but notify the upstream Xft -developers about fixing this bug. - -As of 2022-09-05 this now seems to be finally fixed in libXft 2.3.5: -https://gitlab.freedesktop.org/xorg/lib/libxft/-/blob/libXft-2.3.5/NEWS diff --git a/st/st-0.9.3/LEGACY b/st/st-0.9.3/LEGACY deleted file mode 100644 index bf28b1e..0000000 --- a/st/st-0.9.3/LEGACY +++ /dev/null @@ -1,17 +0,0 @@ -A STATEMENT ON LEGACY SUPPORT - -In the terminal world there is much cruft that comes from old and unsup‐ -ported terminals that inherit incompatible modes and escape sequences -which noone is able to know, except when he/she comes from that time and -developed a graphical vt100 emulator at that time. - -One goal of st is to only support what is really needed. When you en‐ -counter a sequence which you really need, implement it. But while you -are at it, do not add the other cruft you might encounter while sneek‐ -ing at other terminal emulators. History has bloated them and there is -no real evidence that most of the sequences are used today. - - -Christoph Lohmann <20h@r-36.net> -2012-09-13T07:00:36.081271045+02:00 - diff --git a/st/st-0.9.3/LICENSE b/st/st-0.9.3/LICENSE deleted file mode 100644 index 3cbf420..0000000 --- a/st/st-0.9.3/LICENSE +++ /dev/null @@ -1,34 +0,0 @@ -MIT/X Consortium License - -© 2014-2022 Hiltjo Posthuma <hiltjo at codemadness dot org> -© 2018 Devin J. Pohly <djpohly at gmail dot com> -© 2014-2017 Quentin Rameau <quinq at fifth dot space> -© 2009-2012 Aurélien APTEL <aurelien dot aptel at gmail dot com> -© 2008-2017 Anselm R Garbe <garbeam at gmail dot com> -© 2012-2017 Roberto E. Vargas Caballero <k0ga at shike2 dot com> -© 2012-2016 Christoph Lohmann <20h at r-36 dot net> -© 2013 Eon S. Jeon <esjeon at hyunmu dot am> -© 2013 Alexander Sedov <alex0player at gmail dot com> -© 2013 Mark Edgar <medgar123 at gmail dot com> -© 2013-2014 Eric Pruitt <eric.pruitt at gmail dot com> -© 2013 Michael Forney <mforney at mforney dot org> -© 2013-2014 Markus Teich <markus dot teich at stusta dot mhn dot de> -© 2014-2015 Laslo Hunhold <dev at frign dot de> - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/st/st-0.9.3/Makefile b/st/st-0.9.3/Makefile deleted file mode 100644 index 15db421..0000000 --- a/st/st-0.9.3/Makefile +++ /dev/null @@ -1,51 +0,0 @@ -# st - simple terminal -# See LICENSE file for copyright and license details. -.POSIX: - -include config.mk - -SRC = st.c x.c -OBJ = $(SRC:.c=.o) - -all: st - -config.h: - cp config.def.h config.h - -.c.o: - $(CC) $(STCFLAGS) -c $< - -st.o: config.h st.h win.h -x.o: arg.h config.h st.h win.h - -$(OBJ): config.h config.mk - -st: $(OBJ) - $(CC) -o $@ $(OBJ) $(STLDFLAGS) - -clean: - rm -f st $(OBJ) st-$(VERSION).tar.gz - -dist: clean - mkdir -p st-$(VERSION) - cp -R FAQ LEGACY TODO LICENSE Makefile README config.mk\ - config.def.h st.info st.1 arg.h st.h win.h $(SRC)\ - st-$(VERSION) - tar -cf - st-$(VERSION) | gzip > st-$(VERSION).tar.gz - rm -rf st-$(VERSION) - -install: st - mkdir -p $(DESTDIR)$(PREFIX)/bin - cp -f st $(DESTDIR)$(PREFIX)/bin - chmod 755 $(DESTDIR)$(PREFIX)/bin/st - mkdir -p $(DESTDIR)$(MANPREFIX)/man1 - sed "s/VERSION/$(VERSION)/g" < st.1 > $(DESTDIR)$(MANPREFIX)/man1/st.1 - chmod 644 $(DESTDIR)$(MANPREFIX)/man1/st.1 - tic -sx st.info - @echo Please see the README file regarding the terminfo entry of st. - -uninstall: - rm -f $(DESTDIR)$(PREFIX)/bin/st - rm -f $(DESTDIR)$(MANPREFIX)/man1/st.1 - -.PHONY: all clean dist install uninstall diff --git a/st/st-0.9.3/README b/st/st-0.9.3/README deleted file mode 100644 index 6a846ed..0000000 --- a/st/st-0.9.3/README +++ /dev/null @@ -1,34 +0,0 @@ -st - simple terminal --------------------- -st is a simple terminal emulator for X which sucks less. - - -Requirements ------------- -In order to build st you need the Xlib header files. - - -Installation ------------- -Edit config.mk to match your local setup (st is installed into -the /usr/local namespace by default). - -Afterwards enter the following command to build and install st (if -necessary as root): - - make clean install - - -Running st ----------- -If you did not install st with make clean install, you must compile -the st terminfo entry with the following command: - - tic -sx st.info - -See the man page for additional details. - -Credits -------- -Based on Aurélien APTEL <aurelien dot aptel at gmail dot com> bt source code. - diff --git a/st/st-0.9.3/TODO b/st/st-0.9.3/TODO deleted file mode 100644 index 5f74cd5..0000000 --- a/st/st-0.9.3/TODO +++ /dev/null @@ -1,28 +0,0 @@ -vt emulation ------------- - -* double-height support - -code & interface ----------------- - -* add a simple way to do multiplexing - -drawing -------- -* add diacritics support to xdraws() - * switch to a suckless font drawing library -* make the font cache simpler -* add better support for brightening of the upper colors - -bugs ----- - -* fix shift up/down (shift selection in emacs) -* remove DEC test sequence when appropriate - -misc ----- - - $ grep -nE 'XXX|TODO' st.c - diff --git a/st/st-0.9.3/arg.h b/st/st-0.9.3/arg.h deleted file mode 100644 index a22e019..0000000 --- a/st/st-0.9.3/arg.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copy me if you can. - * by 20h - */ - -#ifndef ARG_H__ -#define ARG_H__ - -extern char *argv0; - -/* use main(int argc, char *argv[]) */ -#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\ - argv[0] && argv[0][0] == '-'\ - && argv[0][1];\ - argc--, argv++) {\ - char argc_;\ - char **argv_;\ - int brk_;\ - if (argv[0][1] == '-' && argv[0][2] == '\0') {\ - argv++;\ - argc--;\ - break;\ - }\ - int i_;\ - for (i_ = 1, brk_ = 0, argv_ = argv;\ - argv[0][i_] && !brk_;\ - i_++) {\ - if (argv_ != argv)\ - break;\ - argc_ = argv[0][i_];\ - switch (argc_) - -#define ARGEND }\ - } - -#define ARGC() argc_ - -#define EARGF(x) ((argv[0][i_+1] == '\0' && argv[1] == NULL)?\ - ((x), abort(), (char *)0) :\ - (brk_ = 1, (argv[0][i_+1] != '\0')?\ - (&argv[0][i_+1]) :\ - (argc--, argv++, argv[0]))) - -#define ARGF() ((argv[0][i_+1] == '\0' && argv[1] == NULL)?\ - (char *)0 :\ - (brk_ = 1, (argv[0][i_+1] != '\0')?\ - (&argv[0][i_+1]) :\ - (argc--, argv++, argv[0]))) - -#endif diff --git a/st/st-0.9.3/config.def.h b/st/st-0.9.3/config.def.h deleted file mode 100644 index 5a1072f..0000000 --- a/st/st-0.9.3/config.def.h +++ /dev/null @@ -1,503 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -/* - * appearance - * - * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html - */ -static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; -static int borderpx = 2; - -/* - * What program is execed by st depends of these precedence rules: - * 1: program passed with -e - * 2: scroll and/or utmp - * 3: SHELL environment variable - * 4: value of shell in /etc/passwd - * 5: value of shell in config.h - */ -static char *shell = "/bin/sh"; -char *utmp = NULL; -/* scroll program: to enable use a string like "scroll" */ -char *scroll = NULL; -char *stty_args = "stty raw pass8 nl -echo -iexten -cstopb 38400"; - -/* identification sequence returned in DA and DECID */ -char *vtiden = "\033[?6c"; - -/* Kerning / character bounding-box multipliers */ -static float cwscale = 1.0; -static float chscale = 1.0; - -/* - * word delimiter string - * - * More advanced example: L" `'\"()[]{}" - */ -wchar_t *worddelimiters = L" "; - -/* selection timeouts (in milliseconds) */ -static unsigned int doubleclicktimeout = 300; -static unsigned int tripleclicktimeout = 600; - -/* alt screens */ -int allowaltscreen = 1; - -/* allow certain non-interactive (insecure) window operations such as: - setting the clipboard text */ -int allowwindowops = 0; - -/* - * draw latency range in ms - from new content/keypress/etc until drawing. - * within this range, st draws when content stops arriving (idle). mostly it's - * near minlatency, but it waits longer for slow updates to avoid partial draw. - * low minlatency will tear/flicker more, as it can "detect" idle too early. - */ -static double minlatency = 2; -static double maxlatency = 33; - -/* - * blinking timeout (set to 0 to disable blinking) for the terminal blinking - * attribute. - */ -static unsigned int blinktimeout = 800; - -/* - * thickness of underline and bar cursors - */ -static unsigned int cursorthickness = 2; - -/* - * bell volume. It must be a value between -100 and 100. Use 0 for disabling - * it - */ -static int bellvolume = 0; - -/* default TERM value */ -char *termname = "st-256color"; - -/* - * spaces per tab - * - * When you are changing this value, don't forget to adapt the »it« value in - * the st.info and appropriately install the st.info in the environment where - * you use this st version. - * - * it#$tabspaces, - * - * Secondly make sure your kernel is not expanding tabs. When running `stty - * -a` »tab0« should appear. You can tell the terminal to not expand tabs by - * running following command: - * - * stty tabs - */ -unsigned int tabspaces = 8; - -/* Terminal colors (16 first used in escape sequence) */ -static const char *colorname[] = { - /* 8 normal colors */ - "black", - "red3", - "green3", - "yellow3", - "Skyblue1", - "magenta3", - "cyan3", - "gray90", - - /* 8 bright colors */ - "gray50", - "red", - "green", - "yellow", - "#5c5cff", - "magenta", - "cyan", - "white", - - [255] = 0, - - /* more colors can be added after 255 to use with DefaultXX */ - "#cccccc", - "#555555", - "gray90", /* default foreground colour */ - "black", /* default background colour */ -}; - - -/* - * Default colors (colorname index) - * foreground, background, cursor, reverse cursor - */ -unsigned int defaultfg = 258; -unsigned int defaultbg = 259; -unsigned int defaultcs = 256; -static unsigned int defaultrcs = 257; - -/* - * Default shape of cursor - * 2: Block ("█") - * 4: Underline ("_") - * 6: Bar ("|") - * 7: Snowman ("☃") - */ -static unsigned int cursorshape = 2; - -/* - * Default columns and rows numbers - */ - -static unsigned int cols = 80; -static unsigned int rows = 24; - -/* - * Default colour and shape of the mouse cursor - */ -static unsigned int mouseshape = XC_xterm; -static unsigned int mousefg = 7; -static unsigned int mousebg = 0; - -/* - * Color used to display font attributes when fontconfig selected a font which - * doesn't match the ones requested. - */ -static unsigned int defaultattr = 11; - -/* - * Force mouse select/shortcuts while mask is active (when MODE_MOUSE is set). - * Note that if you want to use ShiftMask with selmasks, set this to an other - * modifier, set to 0 to not use it. - */ -static uint forcemousemod = ShiftMask; - -/* - * Internal mouse shortcuts. - * Beware that overloading Button1 will disable the selection. - */ -static MouseShortcut mshortcuts[] = { - /* mask button function argument release */ - { XK_ANY_MOD, Button4, kscrollup, {.i = 1}, 0, /* !alt */ -1 }, - { XK_ANY_MOD, Button5, kscrolldown, {.i = 1}, 0, /* !alt */ -1 }, - { XK_ANY_MOD, Button2, selpaste, {.i = 0}, 1 }, - { ShiftMask, Button4, ttysend, {.s = "\033[5;2~"} }, - { XK_ANY_MOD, Button4, ttysend, {.s = "\031"} }, - { ShiftMask, Button5, ttysend, {.s = "\033[6;2~"} }, - { XK_ANY_MOD, Button5, ttysend, {.s = "\005"} }, -}; - -/* Internal keyboard shortcuts. */ -#define MODKEY Mod1Mask -#define TERMMOD (ControlMask|ShiftMask) - -static Shortcut shortcuts[] = { - /* mask keysym function argument */ - { XK_ANY_MOD, XK_Break, sendbreak, {.i = 0} }, - { ControlMask, XK_Print, toggleprinter, {.i = 0} }, - { ShiftMask, XK_Print, printscreen, {.i = 0} }, - { XK_ANY_MOD, XK_Print, printsel, {.i = 0} }, - { TERMMOD, XK_Prior, zoom, {.f = +1} }, - { TERMMOD, XK_Next, zoom, {.f = -1} }, - { TERMMOD, XK_Home, zoomreset, {.f = 0} }, - { TERMMOD, XK_C, clipcopy, {.i = 0} }, - { TERMMOD, XK_V, clippaste, {.i = 0} }, - { TERMMOD, XK_Y, selpaste, {.i = 0} }, - { ShiftMask, XK_Insert, selpaste, {.i = 0} }, - { TERMMOD, XK_Num_Lock, numlock, {.i = 0} }, - { ShiftMask, XK_Page_Up, kscrollup, {.i = -1} }, - { ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} }, - { TERMMOD, XK_space, keyboard_select,{.i = 0} }, -}; - -/* - * Special keys (change & recompile st.info accordingly) - * - * Mask value: - * * Use XK_ANY_MOD to match the key no matter modifiers state - * * Use XK_NO_MOD to match the key alone (no modifiers) - * appkey value: - * * 0: no value - * * > 0: keypad application mode enabled - * * = 2: term.numlock = 1 - * * < 0: keypad application mode disabled - * appcursor value: - * * 0: no value - * * > 0: cursor application mode enabled - * * < 0: cursor application mode disabled - * - * Be careful with the order of the definitions because st searches in - * this table sequentially, so any XK_ANY_MOD must be in the last - * position for a key. - */ - -/* - * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF) - * to be mapped below, add them to this array. - */ -static KeySym mappedkeys[] = { -1 }; - -/* - * State bits to ignore when matching key or button events. By default, - * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored. - */ -static uint ignoremod = Mod2Mask|XK_SWITCH_MOD; - -/* - * This is the huge key array which defines all compatibility to the Linux - * world. Please decide about changes wisely. - */ -static Key key[] = { - /* keysym mask string appkey appcursor */ - { XK_KP_Home, ShiftMask, "\033[2J", 0, -1}, - { XK_KP_Home, ShiftMask, "\033[1;2H", 0, +1}, - { XK_KP_Home, XK_ANY_MOD, "\033[H", 0, -1}, - { XK_KP_Home, XK_ANY_MOD, "\033[1~", 0, +1}, - { XK_KP_Up, XK_ANY_MOD, "\033Ox", +1, 0}, - { XK_KP_Up, XK_ANY_MOD, "\033[A", 0, -1}, - { XK_KP_Up, XK_ANY_MOD, "\033OA", 0, +1}, - { XK_KP_Down, XK_ANY_MOD, "\033Or", +1, 0}, - { XK_KP_Down, XK_ANY_MOD, "\033[B", 0, -1}, - { XK_KP_Down, XK_ANY_MOD, "\033OB", 0, +1}, - { XK_KP_Left, XK_ANY_MOD, "\033Ot", +1, 0}, - { XK_KP_Left, XK_ANY_MOD, "\033[D", 0, -1}, - { XK_KP_Left, XK_ANY_MOD, "\033OD", 0, +1}, - { XK_KP_Right, XK_ANY_MOD, "\033Ov", +1, 0}, - { XK_KP_Right, XK_ANY_MOD, "\033[C", 0, -1}, - { XK_KP_Right, XK_ANY_MOD, "\033OC", 0, +1}, - { XK_KP_Prior, ShiftMask, "\033[5;2~", 0, 0}, - { XK_KP_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, - { XK_KP_Begin, XK_ANY_MOD, "\033[E", 0, 0}, - { XK_KP_End, ControlMask, "\033[J", -1, 0}, - { XK_KP_End, ControlMask, "\033[1;5F", +1, 0}, - { XK_KP_End, ShiftMask, "\033[K", -1, 0}, - { XK_KP_End, ShiftMask, "\033[1;2F", +1, 0}, - { XK_KP_End, XK_ANY_MOD, "\033[4~", 0, 0}, - { XK_KP_Next, ShiftMask, "\033[6;2~", 0, 0}, - { XK_KP_Next, XK_ANY_MOD, "\033[6~", 0, 0}, - { XK_KP_Insert, ShiftMask, "\033[2;2~", +1, 0}, - { XK_KP_Insert, ShiftMask, "\033[4l", -1, 0}, - { XK_KP_Insert, ControlMask, "\033[L", -1, 0}, - { XK_KP_Insert, ControlMask, "\033[2;5~", +1, 0}, - { XK_KP_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, - { XK_KP_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, - { XK_KP_Delete, ControlMask, "\033[M", -1, 0}, - { XK_KP_Delete, ControlMask, "\033[3;5~", +1, 0}, - { XK_KP_Delete, ShiftMask, "\033[2K", -1, 0}, - { XK_KP_Delete, ShiftMask, "\033[3;2~", +1, 0}, - { XK_KP_Delete, XK_ANY_MOD, "\033[P", -1, 0}, - { XK_KP_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, - { XK_KP_Multiply, XK_ANY_MOD, "\033Oj", +2, 0}, - { XK_KP_Add, XK_ANY_MOD, "\033Ok", +2, 0}, - { XK_KP_Enter, XK_ANY_MOD, "\033OM", +2, 0}, - { XK_KP_Enter, XK_ANY_MOD, "\r", -1, 0}, - { XK_KP_Subtract, XK_ANY_MOD, "\033Om", +2, 0}, - { XK_KP_Decimal, XK_ANY_MOD, "\033On", +2, 0}, - { XK_KP_Divide, XK_ANY_MOD, "\033Oo", +2, 0}, - { XK_KP_0, XK_ANY_MOD, "\033Op", +2, 0}, - { XK_KP_1, XK_ANY_MOD, "\033Oq", +2, 0}, - { XK_KP_2, XK_ANY_MOD, "\033Or", +2, 0}, - { XK_KP_3, XK_ANY_MOD, "\033Os", +2, 0}, - { XK_KP_4, XK_ANY_MOD, "\033Ot", +2, 0}, - { XK_KP_5, XK_ANY_MOD, "\033Ou", +2, 0}, - { XK_KP_6, XK_ANY_MOD, "\033Ov", +2, 0}, - { XK_KP_7, XK_ANY_MOD, "\033Ow", +2, 0}, - { XK_KP_8, XK_ANY_MOD, "\033Ox", +2, 0}, - { XK_KP_9, XK_ANY_MOD, "\033Oy", +2, 0}, - { XK_Up, ShiftMask, "\033[1;2A", 0, 0}, - { XK_Up, Mod1Mask, "\033[1;3A", 0, 0}, - { XK_Up, ShiftMask|Mod1Mask,"\033[1;4A", 0, 0}, - { XK_Up, ControlMask, "\033[1;5A", 0, 0}, - { XK_Up, ShiftMask|ControlMask,"\033[1;6A", 0, 0}, - { XK_Up, ControlMask|Mod1Mask,"\033[1;7A", 0, 0}, - { XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A", 0, 0}, - { XK_Up, XK_ANY_MOD, "\033[A", 0, -1}, - { XK_Up, XK_ANY_MOD, "\033OA", 0, +1}, - { XK_Down, ShiftMask, "\033[1;2B", 0, 0}, - { XK_Down, Mod1Mask, "\033[1;3B", 0, 0}, - { XK_Down, ShiftMask|Mod1Mask,"\033[1;4B", 0, 0}, - { XK_Down, ControlMask, "\033[1;5B", 0, 0}, - { XK_Down, ShiftMask|ControlMask,"\033[1;6B", 0, 0}, - { XK_Down, ControlMask|Mod1Mask,"\033[1;7B", 0, 0}, - { XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0, 0}, - { XK_Down, XK_ANY_MOD, "\033[B", 0, -1}, - { XK_Down, XK_ANY_MOD, "\033OB", 0, +1}, - { XK_Left, ShiftMask, "\033[1;2D", 0, 0}, - { XK_Left, Mod1Mask, "\033[1;3D", 0, 0}, - { XK_Left, ShiftMask|Mod1Mask,"\033[1;4D", 0, 0}, - { XK_Left, ControlMask, "\033[1;5D", 0, 0}, - { XK_Left, ShiftMask|ControlMask,"\033[1;6D", 0, 0}, - { XK_Left, ControlMask|Mod1Mask,"\033[1;7D", 0, 0}, - { XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0, 0}, - { XK_Left, XK_ANY_MOD, "\033[D", 0, -1}, - { XK_Left, XK_ANY_MOD, "\033OD", 0, +1}, - { XK_Right, ShiftMask, "\033[1;2C", 0, 0}, - { XK_Right, Mod1Mask, "\033[1;3C", 0, 0}, - { XK_Right, ShiftMask|Mod1Mask,"\033[1;4C", 0, 0}, - { XK_Right, ControlMask, "\033[1;5C", 0, 0}, - { XK_Right, ShiftMask|ControlMask,"\033[1;6C", 0, 0}, - { XK_Right, ControlMask|Mod1Mask,"\033[1;7C", 0, 0}, - { XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0, 0}, - { XK_Right, XK_ANY_MOD, "\033[C", 0, -1}, - { XK_Right, XK_ANY_MOD, "\033OC", 0, +1}, - { XK_ISO_Left_Tab, ShiftMask, "\033[Z", 0, 0}, - { XK_Return, Mod1Mask, "\033\r", 0, 0}, - { XK_Return, XK_ANY_MOD, "\r", 0, 0}, - { XK_Insert, ShiftMask, "\033[4l", -1, 0}, - { XK_Insert, ShiftMask, "\033[2;2~", +1, 0}, - { XK_Insert, ControlMask, "\033[L", -1, 0}, - { XK_Insert, ControlMask, "\033[2;5~", +1, 0}, - { XK_Insert, XK_ANY_MOD, "\033[4h", -1, 0}, - { XK_Insert, XK_ANY_MOD, "\033[2~", +1, 0}, - { XK_Delete, ControlMask, "\033[M", -1, 0}, - { XK_Delete, ControlMask, "\033[3;5~", +1, 0}, - { XK_Delete, ShiftMask, "\033[2K", -1, 0}, - { XK_Delete, ShiftMask, "\033[3;2~", +1, 0}, - { XK_Delete, XK_ANY_MOD, "\033[P", -1, 0}, - { XK_Delete, XK_ANY_MOD, "\033[3~", +1, 0}, - { XK_BackSpace, XK_NO_MOD, "\177", 0, 0}, - { XK_BackSpace, Mod1Mask, "\033\177", 0, 0}, - { XK_Home, ShiftMask, "\033[2J", 0, -1}, - { XK_Home, ShiftMask, "\033[1;2H", 0, +1}, - { XK_Home, XK_ANY_MOD, "\033[H", 0, -1}, - { XK_Home, XK_ANY_MOD, "\033[1~", 0, +1}, - { XK_End, ControlMask, "\033[J", -1, 0}, - { XK_End, ControlMask, "\033[1;5F", +1, 0}, - { XK_End, ShiftMask, "\033[K", -1, 0}, - { XK_End, ShiftMask, "\033[1;2F", +1, 0}, - { XK_End, XK_ANY_MOD, "\033[4~", 0, 0}, - { XK_Prior, ControlMask, "\033[5;5~", 0, 0}, - { XK_Prior, ShiftMask, "\033[5;2~", 0, 0}, - { XK_Prior, XK_ANY_MOD, "\033[5~", 0, 0}, - { XK_Next, ControlMask, "\033[6;5~", 0, 0}, - { XK_Next, ShiftMask, "\033[6;2~", 0, 0}, - { XK_Next, XK_ANY_MOD, "\033[6~", 0, 0}, - { XK_F1, XK_NO_MOD, "\033OP" , 0, 0}, - { XK_F1, /* F13 */ ShiftMask, "\033[1;2P", 0, 0}, - { XK_F1, /* F25 */ ControlMask, "\033[1;5P", 0, 0}, - { XK_F1, /* F37 */ Mod4Mask, "\033[1;6P", 0, 0}, - { XK_F1, /* F49 */ Mod1Mask, "\033[1;3P", 0, 0}, - { XK_F1, /* F61 */ Mod3Mask, "\033[1;4P", 0, 0}, - { XK_F2, XK_NO_MOD, "\033OQ" , 0, 0}, - { XK_F2, /* F14 */ ShiftMask, "\033[1;2Q", 0, 0}, - { XK_F2, /* F26 */ ControlMask, "\033[1;5Q", 0, 0}, - { XK_F2, /* F38 */ Mod4Mask, "\033[1;6Q", 0, 0}, - { XK_F2, /* F50 */ Mod1Mask, "\033[1;3Q", 0, 0}, - { XK_F2, /* F62 */ Mod3Mask, "\033[1;4Q", 0, 0}, - { XK_F3, XK_NO_MOD, "\033OR" , 0, 0}, - { XK_F3, /* F15 */ ShiftMask, "\033[1;2R", 0, 0}, - { XK_F3, /* F27 */ ControlMask, "\033[1;5R", 0, 0}, - { XK_F3, /* F39 */ Mod4Mask, "\033[1;6R", 0, 0}, - { XK_F3, /* F51 */ Mod1Mask, "\033[1;3R", 0, 0}, - { XK_F3, /* F63 */ Mod3Mask, "\033[1;4R", 0, 0}, - { XK_F4, XK_NO_MOD, "\033OS" , 0, 0}, - { XK_F4, /* F16 */ ShiftMask, "\033[1;2S", 0, 0}, - { XK_F4, /* F28 */ ControlMask, "\033[1;5S", 0, 0}, - { XK_F4, /* F40 */ Mod4Mask, "\033[1;6S", 0, 0}, - { XK_F4, /* F52 */ Mod1Mask, "\033[1;3S", 0, 0}, - { XK_F5, XK_NO_MOD, "\033[15~", 0, 0}, - { XK_F5, /* F17 */ ShiftMask, "\033[15;2~", 0, 0}, - { XK_F5, /* F29 */ ControlMask, "\033[15;5~", 0, 0}, - { XK_F5, /* F41 */ Mod4Mask, "\033[15;6~", 0, 0}, - { XK_F5, /* F53 */ Mod1Mask, "\033[15;3~", 0, 0}, - { XK_F6, XK_NO_MOD, "\033[17~", 0, 0}, - { XK_F6, /* F18 */ ShiftMask, "\033[17;2~", 0, 0}, - { XK_F6, /* F30 */ ControlMask, "\033[17;5~", 0, 0}, - { XK_F6, /* F42 */ Mod4Mask, "\033[17;6~", 0, 0}, - { XK_F6, /* F54 */ Mod1Mask, "\033[17;3~", 0, 0}, - { XK_F7, XK_NO_MOD, "\033[18~", 0, 0}, - { XK_F7, /* F19 */ ShiftMask, "\033[18;2~", 0, 0}, - { XK_F7, /* F31 */ ControlMask, "\033[18;5~", 0, 0}, - { XK_F7, /* F43 */ Mod4Mask, "\033[18;6~", 0, 0}, - { XK_F7, /* F55 */ Mod1Mask, "\033[18;3~", 0, 0}, - { XK_F8, XK_NO_MOD, "\033[19~", 0, 0}, - { XK_F8, /* F20 */ ShiftMask, "\033[19;2~", 0, 0}, - { XK_F8, /* F32 */ ControlMask, "\033[19;5~", 0, 0}, - { XK_F8, /* F44 */ Mod4Mask, "\033[19;6~", 0, 0}, - { XK_F8, /* F56 */ Mod1Mask, "\033[19;3~", 0, 0}, - { XK_F9, XK_NO_MOD, "\033[20~", 0, 0}, - { XK_F9, /* F21 */ ShiftMask, "\033[20;2~", 0, 0}, - { XK_F9, /* F33 */ ControlMask, "\033[20;5~", 0, 0}, - { XK_F9, /* F45 */ Mod4Mask, "\033[20;6~", 0, 0}, - { XK_F9, /* F57 */ Mod1Mask, "\033[20;3~", 0, 0}, - { XK_F10, XK_NO_MOD, "\033[21~", 0, 0}, - { XK_F10, /* F22 */ ShiftMask, "\033[21;2~", 0, 0}, - { XK_F10, /* F34 */ ControlMask, "\033[21;5~", 0, 0}, - { XK_F10, /* F46 */ Mod4Mask, "\033[21;6~", 0, 0}, - { XK_F10, /* F58 */ Mod1Mask, "\033[21;3~", 0, 0}, - { XK_F11, XK_NO_MOD, "\033[23~", 0, 0}, - { XK_F11, /* F23 */ ShiftMask, "\033[23;2~", 0, 0}, - { XK_F11, /* F35 */ ControlMask, "\033[23;5~", 0, 0}, - { XK_F11, /* F47 */ Mod4Mask, "\033[23;6~", 0, 0}, - { XK_F11, /* F59 */ Mod1Mask, "\033[23;3~", 0, 0}, - { XK_F12, XK_NO_MOD, "\033[24~", 0, 0}, - { XK_F12, /* F24 */ ShiftMask, "\033[24;2~", 0, 0}, - { XK_F12, /* F36 */ ControlMask, "\033[24;5~", 0, 0}, - { XK_F12, /* F48 */ Mod4Mask, "\033[24;6~", 0, 0}, - { XK_F12, /* F60 */ Mod1Mask, "\033[24;3~", 0, 0}, - { XK_F13, XK_NO_MOD, "\033[1;2P", 0, 0}, - { XK_F14, XK_NO_MOD, "\033[1;2Q", 0, 0}, - { XK_F15, XK_NO_MOD, "\033[1;2R", 0, 0}, - { XK_F16, XK_NO_MOD, "\033[1;2S", 0, 0}, - { XK_F17, XK_NO_MOD, "\033[15;2~", 0, 0}, - { XK_F18, XK_NO_MOD, "\033[17;2~", 0, 0}, - { XK_F19, XK_NO_MOD, "\033[18;2~", 0, 0}, - { XK_F20, XK_NO_MOD, "\033[19;2~", 0, 0}, - { XK_F21, XK_NO_MOD, "\033[20;2~", 0, 0}, - { XK_F22, XK_NO_MOD, "\033[21;2~", 0, 0}, - { XK_F23, XK_NO_MOD, "\033[23;2~", 0, 0}, - { XK_F24, XK_NO_MOD, "\033[24;2~", 0, 0}, - { XK_F25, XK_NO_MOD, "\033[1;5P", 0, 0}, - { XK_F26, XK_NO_MOD, "\033[1;5Q", 0, 0}, - { XK_F27, XK_NO_MOD, "\033[1;5R", 0, 0}, - { XK_F28, XK_NO_MOD, "\033[1;5S", 0, 0}, - { XK_F29, XK_NO_MOD, "\033[15;5~", 0, 0}, - { XK_F30, XK_NO_MOD, "\033[17;5~", 0, 0}, - { XK_F31, XK_NO_MOD, "\033[18;5~", 0, 0}, - { XK_F32, XK_NO_MOD, "\033[19;5~", 0, 0}, - { XK_F33, XK_NO_MOD, "\033[20;5~", 0, 0}, - { XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0}, - { XK_F35, XK_NO_MOD, "\033[23;5~", 0, 0}, -}; - -/* - * Selection types' masks. - * Use the same masks as usual. - * Button1Mask is always unset, to make masks match between ButtonPress. - * ButtonRelease and MotionNotify. - * If no match is found, regular selection is used. - */ -static uint selmasks[] = { - [SEL_RECTANGULAR] = Mod1Mask, -}; - -/* - * Printable characters in ASCII, used to estimate the advance width - * of single wide characters. - */ -static char ascii_printable[] = - " !\"#$%&'()*+,-./0123456789:;<=>?" - "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" - "`abcdefghijklmnopqrstuvwxyz{|}~"; - -/** - + * Undercurl style. Set UNDERCURL_STYLE to one of the available styles. - + * - + * Curly: Dunno how to draw it *shrug* - + * _ _ _ _ - + * ( ) ( ) ( ) ( ) - + * (_) (_) (_) (_) - + * - + * Spiky: - + * /\ /\ /\ /\ - + * \/ \/ \/ - + * - + * Capped: - + * _ _ _ - + * / \ / \ / \ - + * \_/ \_/ - + */ -// Available styles -#define UNDERCURL_CURLY 0 -#define UNDERCURL_SPIKY 1 -#define UNDERCURL_CAPPED 2 -// Active style -#define UNDERCURL_STYLE UNDERCURL_SPIKY diff --git a/st/st-0.9.3/config.mk b/st/st-0.9.3/config.mk deleted file mode 100644 index f5a97f5..0000000 --- a/st/st-0.9.3/config.mk +++ /dev/null @@ -1,36 +0,0 @@ -# st version -VERSION = 0.9.3 - -# Customize below to fit your system - -# paths -PREFIX = ${HOME}/.local -MANPREFIX = $(PREFIX)/share/man - -X11INC = /usr/X11R6/include -X11LIB = /usr/X11R6/lib - -PKG_CONFIG = pkg-config - -# includes and libs -INCS = -I$(X11INC) \ - `$(PKG_CONFIG) --cflags fontconfig` \ - `$(PKG_CONFIG) --cflags freetype2` -LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft \ - `$(PKG_CONFIG) --libs fontconfig` \ - `$(PKG_CONFIG) --libs freetype2` - -# flags -STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 -STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS) -STLDFLAGS = $(LIBS) $(LDFLAGS) - -# OpenBSD: -#CPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -#LIBS = -L$(X11LIB) -lm -lX11 -lutil -lXft \ -# `$(PKG_CONFIG) --libs fontconfig` \ -# `$(PKG_CONFIG) --libs freetype2` -#MANPREFIX = ${PREFIX}/man - -# compiler and linker -# CC = c99 diff --git a/st/st-0.9.3/st.1 b/st/st-0.9.3/st.1 deleted file mode 100644 index 39120b4..0000000 --- a/st/st-0.9.3/st.1 +++ /dev/null @@ -1,177 +0,0 @@ -.TH ST 1 st\-VERSION -.SH NAME -st \- simple terminal -.SH SYNOPSIS -.B st -.RB [ \-aiv ] -.RB [ \-c -.IR class ] -.RB [ \-f -.IR font ] -.RB [ \-g -.IR geometry ] -.RB [ \-n -.IR name ] -.RB [ \-o -.IR iofile ] -.RB [ \-T -.IR title ] -.RB [ \-t -.IR title ] -.RB [ \-l -.IR line ] -.RB [ \-w -.IR windowid ] -.RB [[ \-e ] -.IR command -.RI [ arguments ...]] -.PP -.B st -.RB [ \-aiv ] -.RB [ \-c -.IR class ] -.RB [ \-f -.IR font ] -.RB [ \-g -.IR geometry ] -.RB [ \-n -.IR name ] -.RB [ \-o -.IR iofile ] -.RB [ \-T -.IR title ] -.RB [ \-t -.IR title ] -.RB [ \-w -.IR windowid ] -.RB \-l -.IR line -.RI [ stty_args ...] -.SH DESCRIPTION -.B st -is a simple terminal emulator. -.SH OPTIONS -.TP -.B \-a -disable alternate screens in terminal -.TP -.BI \-c " class" -defines the window class (default $TERM). -.TP -.BI \-f " font" -defines the -.I font -to use when st is run. -.TP -.BI \-g " geometry" -defines the X11 geometry string. -The form is [=][<cols>{xX}<rows>][{+-}<xoffset>{+-}<yoffset>]. See -.BR XParseGeometry (3) -for further details. -.TP -.B \-i -will fixate the position given with the -g option. -.TP -.BI \-n " name" -defines the window instance name (default $TERM). -.TP -.BI \-o " iofile" -writes all the I/O to -.I iofile. -This feature is useful when recording st sessions. A value of "-" means -standard output. -.TP -.BI \-T " title" -defines the window title (default 'st'). -.TP -.BI \-t " title" -defines the window title (default 'st'). -.TP -.BI \-w " windowid" -embeds st within the window identified by -.I windowid -.TP -.BI \-l " line" -use a tty -.I line -instead of a pseudo terminal. -.I line -should be a (pseudo-)serial device (e.g. /dev/ttyS0 on Linux for serial port -0). -When this flag is given -remaining arguments are used as flags for -.BR stty(1). -By default st initializes the serial line to 8 bits, no parity, 1 stop bit -and a 38400 baud rate. The speed is set by appending it as last argument -(e.g. 'st -l /dev/ttyS0 115200'). Arguments before the last one are -.BR stty(1) -flags. If you want to set odd parity on 115200 baud use for example 'st -l -/dev/ttyS0 parenb parodd 115200'. Set the number of bits by using for -example 'st -l /dev/ttyS0 cs7 115200'. See -.BR stty(1) -for more arguments and cases. -.TP -.B \-v -prints version information to stderr, then exits. -.TP -.BI \-e " command " [ " arguments " "... ]" -st executes -.I command -instead of the shell. If this is used it -.B must be the last option -on the command line, as in xterm / rxvt. -This option is only intended for compatibility, -and all the remaining arguments are used as a command -even without it. -.SH SHORTCUTS -.TP -.B Break -Send a break in the serial line. -Break key is obtained in PC keyboards -pressing at the same time control and pause. -.TP -.B Ctrl-Print Screen -Toggle if st should print to the -.I iofile. -.TP -.B Shift-Print Screen -Print the full screen to the -.I iofile. -.TP -.B Print Screen -Print the selection to the -.I iofile. -.TP -.B Ctrl-Shift-Page Up -Increase font size. -.TP -.B Ctrl-Shift-Page Down -Decrease font size. -.TP -.B Ctrl-Shift-Home -Reset to default font size. -.TP -.B Ctrl-Shift-y -Paste from primary selection (middle mouse button). -.TP -.B Ctrl-Shift-c -Copy the selected text to the clipboard selection. -.TP -.B Ctrl-Shift-v -Paste from the clipboard selection. -.SH CUSTOMIZATION -.B st -can be customized by creating a custom config.h and (re)compiling the source -code. This keeps it fast, secure and simple. -.SH AUTHORS -See the LICENSE file for the authors. -.SH LICENSE -See the LICENSE file for the terms of redistribution. -.SH SEE ALSO -.BR tabbed (1), -.BR utmp (1), -.BR stty (1), -.BR scroll (1) -.SH BUGS -See the TODO file in the distribution. - diff --git a/st/st-0.9.3/st.c b/st/st-0.9.3/st.c deleted file mode 100644 index 9f2df77..0000000 --- a/st/st-0.9.3/st.c +++ /dev/null @@ -1,3414 +0,0 @@ -/* See LICENSE for license details. */ -#include <ctype.h> -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <pwd.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <signal.h> -#include <sys/ioctl.h> -#include <sys/select.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <termios.h> -#include <unistd.h> -#include <wchar.h> -#include <X11/keysym.h> -#include <X11/X.h> - -#include "st.h" -#include "win.h" - -#if defined(__linux) -#include <pty.h> -#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) -#include <util.h> -#elif defined(__FreeBSD__) || defined(__DragonFly__) -#include <libutil.h> -#endif - -/* Arbitrary sizes */ -#define UTF_INVALID 0xFFFD -#define UTF_SIZ 4 -#define ESC_BUF_SIZ (128*UTF_SIZ) -#define ESC_ARG_SIZ 16 -#define CAR_PER_ARG 4 -#define STR_BUF_SIZ ESC_BUF_SIZ -#define STR_ARG_SIZ ESC_ARG_SIZ -#define HISTSIZE 2000 -#define RESIZEBUFFER 1000 - -/* macros */ -#define IS_SET(flag) ((term.mode & (flag)) != 0) -#define ISCONTROLC0(c) (BETWEEN(c, 0, 0x1f) || (c) == 0x7f) -#define ISCONTROLC1(c) (BETWEEN(c, 0x80, 0x9f)) -#define ISCONTROL(c) (ISCONTROLC0(c) || ISCONTROLC1(c)) -#define ISDELIM(u) (u && wcschr(worddelimiters, u)) -#define TLINE(y) ( \ - (y) < term.scr ? term.hist[(term.histi + (y) - term.scr + 1 + HISTSIZE) % HISTSIZE] \ - : term.line[(y) - term.scr] \ - ) - -#define TLINEABS(y) ( \ - (y) < 0 ? term.hist[(term.histi + (y) + 1 + HISTSIZE) % HISTSIZE] : term.line[(y)] \ - ) - -#define UPDATEWRAPNEXT(alt, col) do { \ - if ((term.c.state & CURSOR_WRAPNEXT) && term.c.x + term.wrapcwidth[alt] < col) { \ - term.c.x += term.wrapcwidth[alt]; \ - term.c.state &= ~CURSOR_WRAPNEXT; \ - } \ - } while (0); - -enum term_mode { - MODE_WRAP = 1 << 0, - MODE_INSERT = 1 << 1, - MODE_ALTSCREEN = 1 << 2, - MODE_CRLF = 1 << 3, - MODE_ECHO = 1 << 4, - MODE_PRINT = 1 << 5, - MODE_UTF8 = 1 << 6, -}; - -enum scroll_mode { - SCROLL_RESIZE = -1, - SCROLL_NOSAVEHIST = 0, - SCROLL_SAVEHIST = 1 -}; - -enum cursor_movement { - CURSOR_SAVE, - CURSOR_LOAD -}; - -enum cursor_state { - CURSOR_DEFAULT = 0, - CURSOR_WRAPNEXT = 1, - CURSOR_ORIGIN = 2 -}; - -enum charset { - CS_GRAPHIC0, - CS_GRAPHIC1, - CS_UK, - CS_USA, - CS_MULTI, - CS_GER, - CS_FIN -}; - -enum escape_state { - ESC_START = 1, - ESC_CSI = 2, - ESC_STR = 4, /* DCS, OSC, PM, APC */ - ESC_ALTCHARSET = 8, - ESC_STR_END = 16, /* a final string was encountered */ - ESC_TEST = 32, /* Enter in test mode */ - ESC_UTF8 = 64, -}; - -typedef struct { - Glyph attr; /* current char attributes */ - int x; - int y; - char state; -} TCursor; - -typedef struct { - int mode; - int type; - int snap; - /* - * Selection variables: - * nb – normalized coordinates of the beginning of the selection - * ne – normalized coordinates of the end of the selection - * ob – original coordinates of the beginning of the selection - * oe – original coordinates of the end of the selection - */ - struct { - int x, y; - } nb, ne, ob, oe; - - int alt; -} Selection; - -/* Internal representation of the screen */ -typedef struct { - int row; /* nb row */ - int col; /* nb col */ - Line *line; /* screen */ - Line hist[HISTSIZE]; /* history buffer */ - int histi; /* history index */ - int histf; /* nb history available */ - int scr; /* scroll back */ - int wrapcwidth[2]; /* used in updating WRAPNEXT when resizing */ - int *dirty; /* dirtyness of lines */ - TCursor c; /* cursor */ - int ocx; /* old cursor col */ - int ocy; /* old cursor row */ - int top; /* top scroll limit */ - int bot; /* bottom scroll limit */ - int mode; /* terminal mode flags */ - int esc; /* escape state flags */ - char trantbl[4]; /* charset table translation */ - int charset; /* current charset */ - int icharset; /* selected charset for sequence */ - int *tabs; - Rune lastc; /* last printed char outside of sequence, 0 if control */ -} Term; - -/* CSI Escape sequence structs */ -/* ESC '[' [[ [<priv>] <arg> [;]] <mode> [<mode>]] */ -typedef struct { - char buf[ESC_BUF_SIZ]; /* raw string */ - size_t len; /* raw string length */ - char priv; - int arg[ESC_ARG_SIZ]; - int narg; /* nb of args */ - char mode[2]; - int carg[ESC_ARG_SIZ][CAR_PER_ARG]; /* colon args */ -} CSIEscape; - -/* STR Escape sequence structs */ -/* ESC type [[ [<priv>] <arg> [;]] <mode>] ESC '\' */ -typedef struct { - char type; /* ESC type ... */ - char *buf; /* allocated raw string */ - size_t siz; /* allocation size */ - size_t len; /* raw string length */ - char *args[STR_ARG_SIZ]; - int narg; /* nb of args */ -} STREscape; - -static void execsh(char *, char **); -static void stty(char **); -static void sigchld(int); -static void ttywriteraw(const char *, size_t); - -static void csidump(void); -static void csihandle(void); -static void readcolonargs(char **, int, int[][CAR_PER_ARG]); -static void csiparse(void); -static void csireset(void); -static void osc_color_response(int, int, int); -static int eschandle(uchar); -static void strdump(void); -static void strhandle(void); -static void strparse(void); -static void strreset(void); - -static void tprinter(char *, size_t); -static void tdumpsel(void); -static void tdumpline(int); -static void tdump(void); -static void tclearregion(int, int, int, int, int); -static void tcursor(int); -static void tclearglyph(Glyph *, int); -static void tresetcursor(void); -static void tdeletechar(int); -static void tdeleteline(int); -static void tinsertblank(int); -static void tinsertblankline(int); -static int tlinelen(Line len); -static int tiswrapped(Line line); -static char *tgetglyphs(char *, const Glyph *, const Glyph *); -static size_t tgetline(char *, const Glyph *); -static void tmoveto(int, int); -static void tmoveato(int, int); -static void tnewline(int); -static void tputtab(int); -static void tputc(Rune); -static void treset(void); -static void tscrollup(int, int, int, int); -static void tscrolldown(int, int); -static void treflow(int, int); -static void rscrolldown(int); -static void tresizedef(int, int); -static void tresizealt(int, int); -static void tsetattr(const int *, int); -static void tsetchar(Rune, const Glyph *, int, int); -static void tsetdirt(int, int); -static void tsetscroll(int, int); -static void tswapscreen(void); -static void tloaddefscreen(int, int); -static void tloadaltscreen(int, int); -static void tsetmode(int, int, const int *, int); -static int twrite(const char *, int, int); -static void tfulldirt(void); -static void tcontrolcode(uchar ); -static void tdectest(char ); -static void tdefutf8(char); -static int32_t tdefcolor(const int *, int *, int); -static void tdeftran(char); -static void tstrsequence(uchar); - -static void drawregion(int, int, int, int); - -static void selnormalize(void); -static void selscroll(int, int, int); -static void selmove(int); -static void selremove(void); -static int regionselected(int, int, int, int); -static void selsnap(int *, int *, int); - -static size_t utf8decode(const char *, Rune *, size_t); -static Rune utf8decodebyte(char, size_t *); -static char utf8encodebyte(Rune, size_t); -static size_t utf8validate(Rune *, size_t); - -static char *base64dec(const char *); -static char base64dec_getc(const char **); - -static ssize_t xwrite(int, const char *, size_t); - -/* Globals */ -static Term term; -static Selection sel; -static CSIEscape csiescseq; -static STREscape strescseq; -static int iofd = 1; -static int cmdfd; -static pid_t pid; - -static const uchar utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; -static const uchar utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; -static const Rune utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; -static const Rune utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; - -ssize_t -xwrite(int fd, const char *s, size_t len) -{ - size_t aux = len; - ssize_t r; - - while (len > 0) { - r = write(fd, s, len); - if (r < 0) - return r; - len -= r; - s += r; - } - - return aux; -} - -void * -xmalloc(size_t len) -{ - void *p; - - if (!(p = malloc(len))) - die("malloc: %s\n", strerror(errno)); - - return p; -} - -void * -xrealloc(void *p, size_t len) -{ - if ((p = realloc(p, len)) == NULL) - die("realloc: %s\n", strerror(errno)); - - return p; -} - -char * -xstrdup(const char *s) -{ - char *p; - - if ((p = strdup(s)) == NULL) - die("strdup: %s\n", strerror(errno)); - - return p; -} - -size_t -utf8decode(const char *c, Rune *u, size_t clen) -{ - size_t i, j, len, type; - Rune udecoded; - - *u = UTF_INVALID; - if (!clen) - return 0; - udecoded = utf8decodebyte(c[0], &len); - if (!BETWEEN(len, 1, UTF_SIZ)) - return 1; - for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { - udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); - if (type != 0) - return j; - } - if (j < len) - return 0; - *u = udecoded; - utf8validate(u, len); - - return len; -} - -Rune -utf8decodebyte(char c, size_t *i) -{ - for (*i = 0; *i < LEN(utfmask); ++(*i)) - if (((uchar)c & utfmask[*i]) == utfbyte[*i]) - return (uchar)c & ~utfmask[*i]; - - return 0; -} - -size_t -utf8encode(Rune u, char *c) -{ - size_t len, i; - - len = utf8validate(&u, 0); - if (len > UTF_SIZ) - return 0; - - for (i = len - 1; i != 0; --i) { - c[i] = utf8encodebyte(u, 0); - u >>= 6; - } - c[0] = utf8encodebyte(u, len); - - return len; -} - -char -utf8encodebyte(Rune u, size_t i) -{ - return utfbyte[i] | (u & ~utfmask[i]); -} - -size_t -utf8validate(Rune *u, size_t i) -{ - if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) - *u = UTF_INVALID; - for (i = 1; *u > utfmax[i]; ++i) - ; - - return i; -} - -char -base64dec_getc(const char **src) -{ - while (**src && !isprint((unsigned char)**src)) - (*src)++; - return **src ? *((*src)++) : '='; /* emulate padding if string ends */ -} - -char * -base64dec(const char *src) -{ - size_t in_len = strlen(src); - char *result, *dst; - static const char base64_digits[256] = { - [43] = 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 0, 0, 0, -1, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, - 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 - }; - - if (in_len % 4) - in_len += 4 - (in_len % 4); - result = dst = xmalloc(in_len / 4 * 3 + 1); - while (*src) { - int a = base64_digits[(unsigned char) base64dec_getc(&src)]; - int b = base64_digits[(unsigned char) base64dec_getc(&src)]; - int c = base64_digits[(unsigned char) base64dec_getc(&src)]; - int d = base64_digits[(unsigned char) base64dec_getc(&src)]; - - /* invalid input. 'a' can be -1, e.g. if src is "\n" (c-str) */ - if (a == -1 || b == -1) - break; - - *dst++ = (a << 2) | ((b & 0x30) >> 4); - if (c == -1) - break; - *dst++ = ((b & 0x0f) << 4) | ((c & 0x3c) >> 2); - if (d == -1) - break; - *dst++ = ((c & 0x03) << 6) | d; - } - *dst = '\0'; - return result; -} - -void -selinit(void) -{ - sel.mode = SEL_IDLE; - sel.snap = 0; - sel.ob.x = -1; -} - -int -tlinelen(Line line) -{ - int i = term.col - 1; - - for (; i >= 0 && !(line[i].mode & (ATTR_SET | ATTR_WRAP)); i--); - return i + 1; -} - -int -tiswrapped(Line line) -{ - int len = tlinelen(line); - - return len > 0 && (line[len - 1].mode & ATTR_WRAP); -} - -char * -tgetglyphs(char *buf, const Glyph *gp, const Glyph *lgp) -{ - while (gp <= lgp) - if (gp->mode & ATTR_WDUMMY) { - gp++; - } else { - buf += utf8encode((gp++)->u, buf); - } - return buf; -} - -size_t -tgetline(char *buf, const Glyph *fgp) -{ - char *ptr; - const Glyph *lgp = &fgp[term.col - 1]; - - while (lgp > fgp && !(lgp->mode & (ATTR_SET | ATTR_WRAP))) - lgp--; - ptr = tgetglyphs(buf, fgp, lgp); - if (!(lgp->mode & ATTR_WRAP)) - *(ptr++) = '\n'; - return ptr - buf; -} - -void -selstart(int col, int row, int snap) -{ - selclear(); - sel.mode = SEL_EMPTY; - sel.type = SEL_REGULAR; - sel.alt = IS_SET(MODE_ALTSCREEN); - sel.snap = snap; - sel.oe.x = sel.ob.x = col; - sel.oe.y = sel.ob.y = row; - selnormalize(); - - if (sel.snap != 0) - sel.mode = SEL_READY; - tsetdirt(sel.nb.y, sel.ne.y); -} - -void -selextend(int col, int row, int type, int done) -{ - int oldey, oldex, oldsby, oldsey, oldtype; - - if (sel.mode == SEL_IDLE) - return; - if (done && sel.mode == SEL_EMPTY) { - selclear(); - return; - } - - oldey = sel.oe.y; - oldex = sel.oe.x; - oldsby = sel.nb.y; - oldsey = sel.ne.y; - oldtype = sel.type; - - sel.oe.x = col; - sel.oe.y = row; - sel.type = type; - selnormalize(); - - if (oldey != sel.oe.y || oldex != sel.oe.x || - oldtype != sel.type || sel.mode == SEL_EMPTY) - tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey)); - - sel.mode = done ? SEL_IDLE : SEL_READY; -} - -void -selnormalize(void) -{ - int i; - - if (sel.type == SEL_REGULAR && sel.ob.y != sel.oe.y) { - sel.nb.x = sel.ob.y < sel.oe.y ? sel.ob.x : sel.oe.x; - sel.ne.x = sel.ob.y < sel.oe.y ? sel.oe.x : sel.ob.x; - } else { - sel.nb.x = MIN(sel.ob.x, sel.oe.x); - sel.ne.x = MAX(sel.ob.x, sel.oe.x); - } - sel.nb.y = MIN(sel.ob.y, sel.oe.y); - sel.ne.y = MAX(sel.ob.y, sel.oe.y); - - selsnap(&sel.nb.x, &sel.nb.y, -1); - selsnap(&sel.ne.x, &sel.ne.y, +1); - - /* expand selection over line breaks */ - if (sel.type == SEL_RECTANGULAR) - return; - - i = tlinelen(TLINE(sel.nb.y)); - if (sel.nb.x > i) - sel.nb.x = i; - if (sel.ne.x >= tlinelen(TLINE(sel.ne.y))) - sel.ne.x = term.col - 1; -} - -int -regionselected(int x1, int y1, int x2, int y2) -{ - if (sel.ob.x == -1 || sel.mode == SEL_EMPTY || - sel.alt != IS_SET(MODE_ALTSCREEN) || sel.nb.y > y2 || sel.ne.y < y1) - return 0; - - return (sel.type == SEL_RECTANGULAR) ? sel.nb.x <= x2 && sel.ne.x >= x1 - : (sel.nb.y != y2 || sel.nb.x <= x2) && - (sel.ne.y != y1 || sel.ne.x >= x1); -} - -int -selected(int x, int y) -{ - return regionselected(x, y, x, y); -} - - -void -selsnap(int *x, int *y, int direction) -{ - int newx, newy, xt, yt; - int rtop = 0, rbot = term.row - 1; - int delim, prevdelim; - const Glyph *gp, *prevgp; - - if (!IS_SET(MODE_ALTSCREEN)) - rtop += -term.histf + term.scr, rbot += term.scr; - - switch (sel.snap) { - case SNAP_WORD: - /* - * Snap around if the word wraps around at the end or - * beginning of a line. - */ - prevgp = &TLINE(*y)[*x]; - prevdelim = ISDELIM(prevgp->u); - for (;;) { - newx = *x + direction; - newy = *y; - if (!BETWEEN(newx, 0, term.col - 1)) { - newy += direction; - newx = (newx + term.col) % term.col; - if (!BETWEEN(newy, rtop, rbot)) - break; - - if (direction > 0) - yt = *y, xt = *x; - else - yt = newy, xt = newx; - if (!(TLINE(yt)[xt].mode & ATTR_WRAP)) - break; - } - - if (newx >= tlinelen(TLINE(newy))) - break; - - gp = &TLINE(newy)[newx]; - delim = ISDELIM(gp->u); - if (!(gp->mode & ATTR_WDUMMY) && (delim != prevdelim || - (delim && !(gp->u == ' ' && prevgp->u == ' ')))) - break; - - *x = newx; - *y = newy; - prevgp = gp; - prevdelim = delim; - } - break; - case SNAP_LINE: - /* - * Snap around if the the previous line or the current one - * has set ATTR_WRAP at its end. Then the whole next or - * previous line will be selected. - */ - *x = (direction < 0) ? 0 : term.col - 1; - if (direction < 0) { - for (; *y > rtop; *y -= 1) { - if (!tiswrapped(TLINE(*y-1))) - break; - } - } else if (direction > 0) { - for (; *y < rbot; *y += 1) { - if (!tiswrapped(TLINE(*y))) - break; - } - } - break; - } -} - -char * -getsel(void) -{ - char *str, *ptr; - int y, lastx, linelen; - const Glyph *gp, *lgp; - - if (sel.ob.x == -1 || sel.alt != IS_SET(MODE_ALTSCREEN)) - return NULL; - - str = xmalloc((term.col + 1) * (sel.ne.y - sel.nb.y + 1) * UTF_SIZ); - ptr = str; - - /* append every set & selected glyph to the selection */ - for (y = sel.nb.y; y <= sel.ne.y; y++) { - Line line = TLINE(y); - - if ((linelen = tlinelen(line)) == 0) { - *ptr++ = '\n'; - continue; - } - - if (sel.type == SEL_RECTANGULAR) { - gp = &line[sel.nb.x]; - lastx = sel.ne.x; - } else { - gp = &line[sel.nb.y == y ? sel.nb.x : 0]; - lastx = (sel.ne.y == y) ? sel.ne.x : term.col-1; - } - lgp = &line[MIN(lastx, linelen-1)]; - - ptr = tgetglyphs(ptr, gp, lgp); - - /* - * Copy and pasting of line endings is inconsistent - * in the inconsistent terminal and GUI world. - * The best solution seems like to produce '\n' when - * something is copied from st and convert '\n' to - * '\r', when something to be pasted is received by - * st. - * FIXME: Fix the computer world. - */ - if ((y < sel.ne.y || lastx >= linelen) && - (!(lgp->mode & ATTR_WRAP) || sel.type == SEL_RECTANGULAR)) - *ptr++ = '\n'; - } - *ptr = '\0'; - return str; -} - -void -selclear(void) -{ - if (sel.ob.x == -1) - return; - selremove(); - tsetdirt(sel.nb.y, sel.ne.y); -} - -void -selremove(void) -{ - sel.mode = SEL_IDLE; - sel.ob.x = -1; -} - -void -die(const char *errstr, ...) -{ - va_list ap; - - va_start(ap, errstr); - vfprintf(stderr, errstr, ap); - va_end(ap); - exit(1); -} - -void -execsh(char *cmd, char **args) -{ - char *sh, *prog, *arg; - const struct passwd *pw; - - errno = 0; - if ((pw = getpwuid(getuid())) == NULL) { - if (errno) - die("getpwuid: %s\n", strerror(errno)); - else - die("who are you?\n"); - } - - if ((sh = getenv("SHELL")) == NULL) - sh = (pw->pw_shell[0]) ? pw->pw_shell : cmd; - - if (args) { - prog = args[0]; - arg = NULL; - } else if (scroll) { - prog = scroll; - arg = utmp ? utmp : sh; - } else if (utmp) { - prog = utmp; - arg = NULL; - } else { - prog = sh; - arg = NULL; - } - DEFAULT(args, ((char *[]) {prog, arg, NULL})); - - unsetenv("COLUMNS"); - unsetenv("LINES"); - unsetenv("TERMCAP"); - setenv("LOGNAME", pw->pw_name, 1); - setenv("USER", pw->pw_name, 1); - setenv("SHELL", sh, 1); - setenv("HOME", pw->pw_dir, 1); - setenv("TERM", termname, 1); - - signal(SIGCHLD, SIG_DFL); - signal(SIGHUP, SIG_DFL); - signal(SIGINT, SIG_DFL); - signal(SIGQUIT, SIG_DFL); - signal(SIGTERM, SIG_DFL); - signal(SIGALRM, SIG_DFL); - - execvp(prog, args); - _exit(1); -} - -void -sigchld(int a) -{ - int stat; - pid_t p; - - if ((p = waitpid(pid, &stat, WNOHANG)) < 0) - die("waiting for pid %hd failed: %s\n", pid, strerror(errno)); - - if (pid != p) - return; - - if (WIFEXITED(stat) && WEXITSTATUS(stat)) - die("child exited with status %d\n", WEXITSTATUS(stat)); - else if (WIFSIGNALED(stat)) - die("child terminated due to signal %d\n", WTERMSIG(stat)); - _exit(0); -} - -void -stty(char **args) -{ - char cmd[_POSIX_ARG_MAX], **p, *q, *s; - size_t n, siz; - - if ((n = strlen(stty_args)) > sizeof(cmd)-1) - die("incorrect stty parameters\n"); - memcpy(cmd, stty_args, n); - q = cmd + n; - siz = sizeof(cmd) - n; - for (p = args; p && (s = *p); ++p) { - if ((n = strlen(s)) > siz-1) - die("stty parameter length too long\n"); - *q++ = ' '; - memcpy(q, s, n); - q += n; - siz -= n + 1; - } - *q = '\0'; - if (system(cmd) != 0) - perror("Couldn't call stty"); -} - -int -ttynew(const char *line, char *cmd, const char *out, char **args) -{ - int m, s; - - if (out) { - term.mode |= MODE_PRINT; - iofd = (!strcmp(out, "-")) ? - 1 : open(out, O_WRONLY | O_CREAT, 0666); - if (iofd < 0) { - fprintf(stderr, "Error opening %s:%s\n", - out, strerror(errno)); - } - } - - if (line) { - if ((cmdfd = open(line, O_RDWR)) < 0) - die("open line '%s' failed: %s\n", - line, strerror(errno)); - dup2(cmdfd, 0); - stty(args); - return cmdfd; - } - - /* seems to work fine on linux, openbsd and freebsd */ - if (openpty(&m, &s, NULL, NULL, NULL) < 0) - die("openpty failed: %s\n", strerror(errno)); - - switch (pid = fork()) { - case -1: - die("fork failed: %s\n", strerror(errno)); - break; - case 0: - close(iofd); - close(m); - setsid(); /* create a new process group */ - dup2(s, 0); - dup2(s, 1); - dup2(s, 2); - if (ioctl(s, TIOCSCTTY, NULL) < 0) - die("ioctl TIOCSCTTY failed: %s\n", strerror(errno)); - if (s > 2) - close(s); -#ifdef __OpenBSD__ - if (pledge("stdio getpw proc exec", NULL) == -1) - die("pledge\n"); -#endif - execsh(cmd, args); - break; - default: -#ifdef __OpenBSD__ - if (pledge("stdio rpath tty proc", NULL) == -1) - die("pledge\n"); -#endif - close(s); - cmdfd = m; - signal(SIGCHLD, sigchld); - break; - } - return cmdfd; -} - -size_t -ttyread(void) -{ - static char buf[BUFSIZ]; - static int buflen = 0; - int ret, written; - - /* append read bytes to unprocessed bytes */ - ret = read(cmdfd, buf+buflen, LEN(buf)-buflen); - - switch (ret) { - case 0: - exit(0); - case -1: - die("couldn't read from shell: %s\n", strerror(errno)); - default: - buflen += ret; - written = twrite(buf, buflen, 0); - buflen -= written; - /* keep any incomplete UTF-8 byte sequence for the next call */ - if (buflen > 0) - memmove(buf, buf + written, buflen); - return ret; - } -} - -void -ttywrite(const char *s, size_t n, int may_echo) -{ - const char *next; - - kscrolldown(&((Arg){ .i = term.scr })); - - if (may_echo && IS_SET(MODE_ECHO)) - twrite(s, n, 1); - - if (!IS_SET(MODE_CRLF)) { - ttywriteraw(s, n); - return; - } - - /* This is similar to how the kernel handles ONLCR for ttys */ - while (n > 0) { - if (*s == '\r') { - next = s + 1; - ttywriteraw("\r\n", 2); - } else { - next = memchr(s, '\r', n); - DEFAULT(next, s + n); - ttywriteraw(s, next - s); - } - n -= next - s; - s = next; - } -} - -void -ttywriteraw(const char *s, size_t n) -{ - fd_set wfd, rfd; - ssize_t r; - size_t lim = 256; - - /* - * Remember that we are using a pty, which might be a modem line. - * Writing too much will clog the line. That's why we are doing this - * dance. - * FIXME: Migrate the world to Plan 9. - */ - while (n > 0) { - FD_ZERO(&wfd); - FD_ZERO(&rfd); - FD_SET(cmdfd, &wfd); - FD_SET(cmdfd, &rfd); - - /* Check if we can write. */ - if (pselect(cmdfd+1, &rfd, &wfd, NULL, NULL, NULL) < 0) { - if (errno == EINTR) - continue; - die("select failed: %s\n", strerror(errno)); - } - if (FD_ISSET(cmdfd, &wfd)) { - /* - * Only write the bytes written by ttywrite() or the - * default of 256. This seems to be a reasonable value - * for a serial line. Bigger values might clog the I/O. - */ - if ((r = write(cmdfd, s, (n < lim)? n : lim)) < 0) - goto write_error; - if (r < n) { - /* - * We weren't able to write out everything. - * This means the buffer is getting full - * again. Empty it. - */ - if (n < lim) - lim = ttyread(); - n -= r; - s += r; - } else { - /* All bytes have been written. */ - break; - } - } - if (FD_ISSET(cmdfd, &rfd)) - lim = ttyread(); - } - return; - -write_error: - die("write error on tty: %s\n", strerror(errno)); -} - -void -ttyresize(int tw, int th) -{ - struct winsize w; - - w.ws_row = term.row; - w.ws_col = term.col; - w.ws_xpixel = tw; - w.ws_ypixel = th; - if (ioctl(cmdfd, TIOCSWINSZ, &w) < 0) - fprintf(stderr, "Couldn't set window size: %s\n", strerror(errno)); -} - -void -ttyhangup(void) -{ - /* Send SIGHUP to shell */ - kill(pid, SIGHUP); -} - -int -tattrset(int attr) -{ - int i, j; - - for (i = 0; i < term.row-1; i++) { - for (j = 0; j < term.col-1; j++) { - if (term.line[i][j].mode & attr) - return 1; - } - } - - return 0; -} - -void -tsetdirt(int top, int bot) -{ - int i; - - LIMIT(top, 0, term.row-1); - LIMIT(bot, 0, term.row-1); - - for (i = top; i <= bot; i++) - term.dirty[i] = 1; -} - -void -tsetdirtattr(int attr) -{ - int i, j; - - for (i = 0; i < term.row-1; i++) { - for (j = 0; j < term.col-1; j++) { - if (term.line[i][j].mode & attr) { - term.dirty[i] = 1; - break; - } - } - } -} - -int tisaltscr(void) -{ - return IS_SET(MODE_ALTSCREEN); -} - -void -tfulldirt(void) -{ - for (int i = 0; i < term.row; i++) - term.dirty[i] = 1; -} - -void -tcursor(int mode) -{ - static TCursor c[2]; - int alt = IS_SET(MODE_ALTSCREEN); - - if (mode == CURSOR_SAVE) { - c[alt] = term.c; - } else if (mode == CURSOR_LOAD) { - term.c = c[alt]; - tmoveto(c[alt].x, c[alt].y); - } -} - -void -tresetcursor(void) -{ - term.c = (TCursor){ { .mode = ATTR_NULL, .fg = defaultfg, .bg = defaultbg }, - .x = 0, .y = 0, .state = CURSOR_DEFAULT }; -} - -void -treset(void) -{ - uint i; - int x, y; - - tresetcursor(); - - memset(term.tabs, 0, term.col * sizeof(*term.tabs)); - for (i = tabspaces; i < term.col; i += tabspaces) - term.tabs[i] = 1; - term.top = 0; - term.histf = 0; - term.scr = 0; - term.bot = term.row - 1; - term.mode = MODE_WRAP|MODE_UTF8; - memset(term.trantbl, CS_USA, sizeof(term.trantbl)); - term.charset = 0; - - selremove(); - for (i = 0; i < 2; i++) { - tcursor(CURSOR_SAVE); /* reset saved cursor */ - for (y = 0; y < term.row; y++) - for (x = 0; x < term.col; x++) - tclearglyph(&term.line[y][x], 0); - tswapscreen(); - } - tfulldirt(); -} - -void -tnew(int col, int row) -{ - int i, j; - - for (i = 0; i < 2; i++) { - term.line = xmalloc(row * sizeof(Line)); - for (j = 0; j < row; j++) - term.line[j] = xmalloc(col * sizeof(Glyph)); - term.col = col, term.row = row; - tswapscreen(); - } - term.dirty = xmalloc(row * sizeof(*term.dirty)); - term.tabs = xmalloc(col * sizeof(*term.tabs)); - for (i = 0; i < HISTSIZE; i++) - term.hist[i] = xmalloc(col * sizeof(Glyph)); - treset(); -} - -/* handle it with care */ -void -tswapscreen(void) -{ - static Line *altline; - static int altcol, altrow; - Line *tmpline = term.line; - int tmpcol = term.col, tmprow = term.row; - - term.line = altline; - term.col = altcol, term.row = altrow; - altline = tmpline; - altcol = tmpcol, altrow = tmprow; - term.mode ^= MODE_ALTSCREEN; -} - -void -tloaddefscreen(int clear, int loadcursor) -{ - int col, row, alt = IS_SET(MODE_ALTSCREEN); - - if (alt) { - if (clear) - tclearregion(0, 0, term.col-1, term.row-1, 1); - col = term.col, row = term.row; - tswapscreen(); - } - if (loadcursor) - tcursor(CURSOR_LOAD); - if (alt) - tresizedef(col, row); -} - -void -tloadaltscreen(int clear, int savecursor) -{ - int col, row, def = !IS_SET(MODE_ALTSCREEN); - - if (savecursor) - tcursor(CURSOR_SAVE); - if (def) { - col = term.col, row = term.row; - tswapscreen(); - term.scr = 0; - tresizealt(col, row); - } - if (clear) - tclearregion(0, 0, term.col-1, term.row-1, 1); -} - -int -tisaltscreen(void) -{ - return IS_SET(MODE_ALTSCREEN); -} - - -void -kscrolldown(const Arg* a) -{ - int n = a->i; - - if (!term.scr || IS_SET(MODE_ALTSCREEN)) - return; - - if (n < 0) - n = MAX(term.row / -n, 1); - - if (n <= term.scr) { - term.scr -= n; - } else { - n = term.scr; - term.scr = 0; - } - if (sel.ob.x != -1 && !sel.alt) - selmove(-n); /* negate change in term.scr */ - tfulldirt(); -} - - - -void -kscrollup(const Arg* a) -{ - int n = a->i; - - if (!term.histf || IS_SET(MODE_ALTSCREEN)) - return; - - if (n < 0) - n = MAX(term.row / -n, 1); - - if (term.scr + n <= term.histf) { - term.scr += n; - } else { - n = term.histf - term.scr; - term.scr = term.histf; - } - - if (sel.ob.x != -1 && !sel.alt) - selmove(n); /* negate change in term.scr */ - tfulldirt(); - -} - -void -tscrolldown(int top, int n) -{ - int i, bot = term.bot; - Line temp; - - if (n <= 0) - return; - n = MIN(n, bot-top+1); - - tsetdirt(top, bot-n); - tclearregion(0, bot-n+1, term.col-1, bot, 1); - - for (i = bot; i >= top+n; i--) { - temp = term.line[i]; - term.line[i] = term.line[i-n]; - term.line[i-n] = temp; - } - - if (sel.ob.x != -1 && sel.alt == IS_SET(MODE_ALTSCREEN)) - selscroll(top, bot, n); -} - -void -tscrollup(int top, int bot, int n, int mode) -{ - int i, j, s; - int alt = IS_SET(MODE_ALTSCREEN); - int savehist = !alt && top == 0 && mode != SCROLL_NOSAVEHIST; - Line temp; - - if (n <= 0) - return; - n = MIN(n, bot-top+1); - - if (savehist) { - for (i = 0; i < n; i++) { - term.histi = (term.histi + 1) % HISTSIZE; - temp = term.hist[term.histi]; - for (j = 0; j < term.col; j++) - tclearglyph(&temp[j], 1); - term.hist[term.histi] = term.line[i]; - term.line[i] = temp; - } - term.histf = MIN(term.histf + n, HISTSIZE); - s = n; - if (term.scr) { - j = term.scr; - term.scr = MIN(j + n, HISTSIZE); - s = j + n - term.scr; - } - if (mode != SCROLL_RESIZE) - tfulldirt(); - } else { - tclearregion(0, top, term.col-1, top+n-1, 1); - tsetdirt(top+n, bot); - } - - for (i = top; i <= bot-n; i++) { - temp = term.line[i]; - term.line[i] = term.line[i+n]; - term.line[i+n] = temp; - } - - if (sel.ob.x != -1 && sel.alt == alt) { - if (!savehist) { - selscroll(top, bot, -n); - } else if (s > 0) { - selmove(-s); - if (-term.scr + sel.nb.y < -term.histf) - selremove(); - } - } -} - -void -selmove(int n) -{ - sel.ob.y += n, sel.nb.y += n; - sel.oe.y += n, sel.ne.y += n; -} - -void -selscroll(int top, int bot, int n) -{ - /* turn absolute coordinates into relative */ - top += term.scr, bot += term.scr; - - if (BETWEEN(sel.nb.y, top, bot) != BETWEEN(sel.ne.y, top, bot)) { - selclear(); - } else if (BETWEEN(sel.nb.y, top, bot)) { - selmove(n); - if (sel.nb.y < top || sel.ne.y > bot) - selclear(); - } -} - -void -tnewline(int first_col) -{ - int y = term.c.y; - - if (y == term.bot) { - tscrollup(term.top, term.bot, 1, SCROLL_SAVEHIST); - } else { - y++; - } - tmoveto(first_col ? 0 : term.c.x, y); -} - -void -readcolonargs(char **p, int cursor, int params[][CAR_PER_ARG]) -{ - int i = 0; - for (; i < CAR_PER_ARG; i++) - params[cursor][i] = -1; - - if (**p != ':') - return; - - char *np = NULL; - i = 0; - - while (**p == ':' && i < CAR_PER_ARG) { - while (**p == ':') - (*p)++; - params[cursor][i] = strtol(*p, &np, 10); - *p = np; - i++; - } -} - -void -csiparse(void) -{ - char *p = csiescseq.buf, *np; - long int v; - int sep = ';'; /* colon or semi-colon, but not both */ - - csiescseq.narg = 0; - if (*p == '?') { - csiescseq.priv = 1; - p++; - } - - csiescseq.buf[csiescseq.len] = '\0'; - while (p < csiescseq.buf+csiescseq.len) { - np = NULL; - v = strtol(p, &np, 10); - if (np == p) - v = 0; - if (v == LONG_MAX || v == LONG_MIN) - v = -1; - csiescseq.arg[csiescseq.narg++] = v; - p = np; - readcolonargs(&p, csiescseq.narg-1, csiescseq.carg); - if (sep == ';' && *p == ':') - sep = ':'; /* allow override to colon once */ - if (*p != sep || csiescseq.narg == ESC_ARG_SIZ) - break; - p++; - } - csiescseq.mode[0] = *p++; - csiescseq.mode[1] = (p < csiescseq.buf+csiescseq.len) ? *p : '\0'; -} - -/* for absolute user moves, when decom is set */ -void -tmoveato(int x, int y) -{ - tmoveto(x, y + ((term.c.state & CURSOR_ORIGIN) ? term.top: 0)); -} - -void -tmoveto(int x, int y) -{ - int miny, maxy; - - if (term.c.state & CURSOR_ORIGIN) { - miny = term.top; - maxy = term.bot; - } else { - miny = 0; - maxy = term.row - 1; - } - term.c.state &= ~CURSOR_WRAPNEXT; - term.c.x = LIMIT(x, 0, term.col-1); - term.c.y = LIMIT(y, miny, maxy); -} - -void -tsetchar(Rune u, const Glyph *attr, int x, int y) -{ - static const char *vt100_0[62] = { /* 0x41 - 0x7e */ - "↑", "↓", "→", "←", "█", "▚", "☃", /* A - G */ - 0, 0, 0, 0, 0, 0, 0, 0, /* H - O */ - 0, 0, 0, 0, 0, 0, 0, 0, /* P - W */ - 0, 0, 0, 0, 0, 0, 0, " ", /* X - _ */ - "◆", "▒", "␉", "␌", "␍", "␊", "°", "±", /* ` - g */ - "", "␋", "┘", "┐", "┌", "└", "┼", "⎺", /* h - o */ - "⎻", "─", "⎼", "⎽", "├", "┤", "┴", "┬", /* p - w */ - "│", "≤", "≥", "π", "≠", "£", "·", /* x - ~ */ - }; - - /* - * The table is proudly stolen from rxvt. - */ - if (term.trantbl[term.charset] == CS_GRAPHIC0 && - BETWEEN(u, 0x41, 0x7e) && vt100_0[u - 0x41]) - utf8decode(vt100_0[u - 0x41], &u, UTF_SIZ); - - if (term.line[y][x].mode & ATTR_WIDE) { - if (x+1 < term.col) { - term.line[y][x+1].u = ' '; - term.line[y][x+1].mode &= ~ATTR_WDUMMY; - } - } else if (term.line[y][x].mode & ATTR_WDUMMY) { - term.line[y][x-1].u = ' '; - term.line[y][x-1].mode &= ~ATTR_WIDE; - } - - term.dirty[y] = 1; - term.line[y][x] = *attr; - term.line[y][x].u = u; - term.line[y][x].mode |= ATTR_SET; -} - - - -void -tclearglyph(Glyph *gp, int usecurattr) -{ - if (usecurattr) { - gp->fg = term.c.attr.fg; - gp->bg = term.c.attr.bg; - } else { - gp->fg = defaultfg; - gp->bg = defaultbg; - } - gp->mode = ATTR_NULL; - gp->u = ' '; -} - - - -void -tclearregion(int x1, int y1, int x2, int y2, int usecurattr) -{ - int x, y; - /* regionselected() takes relative coordinates */ - if (regionselected(x1+term.scr, y1+term.scr, x2+term.scr, y2+term.scr)) - selremove(); - - for (y = y1; y <= y2; y++) { - term.dirty[y] = 1; - for (x = x1; x <= x2; x++) - tclearglyph(&term.line[y][x], usecurattr); - } -} - -void -tdeletechar(int n) -{ - int src, dst, size; - Line line; - - if (n <= 0) - return; - - dst = term.c.x; - src = MIN(term.c.x + n, term.col); - size = term.col - src; - if (size > 0) { - /* - * otherwise src would point beyond the array - * https://stackoverflow.com/questions/29844298 - */ - line = term.line[term.c.y]; - memmove(&line[dst], &line[src], size * sizeof(Glyph)); - } - tclearregion(dst + size, term.c.y, term.col - 1, term.c.y, 1); -} - -void -tinsertblank(int n) -{ - int src, dst, size; - Line line; - - if (n <= 0) - return; - dst = MIN(term.c.x + n, term.col); - src = term.c.x; - size = term.col - dst; - if (size > 0) { /* otherwise dst would point beyond the array */ - line = term.line[term.c.y]; - memmove(&line[dst], &line[src], size * sizeof(Glyph)); - } - tclearregion(src, term.c.y, dst - 1, term.c.y, 1); -} - -void -tinsertblankline(int n) -{ - if (BETWEEN(term.c.y, term.top, term.bot)) - tscrolldown(term.c.y, n); -} - -void -tdeleteline(int n) -{ - if (BETWEEN(term.c.y, term.top, term.bot)) - tscrollup(term.c.y, term.bot, n, SCROLL_NOSAVEHIST); -} - -int32_t -tdefcolor(const int *attr, int *npar, int l) -{ - int32_t idx = -1; - uint r, g, b; - - switch (attr[*npar + 1]) { - case 2: /* direct color in RGB space */ - if (*npar + 4 >= l) { - fprintf(stderr, - "erresc(38): Incorrect number of parameters (%d)\n", - *npar); - break; - } - r = attr[*npar + 2]; - g = attr[*npar + 3]; - b = attr[*npar + 4]; - *npar += 4; - if (!BETWEEN(r, 0, 255) || !BETWEEN(g, 0, 255) || !BETWEEN(b, 0, 255)) - fprintf(stderr, "erresc: bad rgb color (%u,%u,%u)\n", - r, g, b); - else - idx = TRUECOLOR(r, g, b); - break; - case 5: /* indexed color */ - if (*npar + 2 >= l) { - fprintf(stderr, - "erresc(38): Incorrect number of parameters (%d)\n", - *npar); - break; - } - *npar += 2; - if (!BETWEEN(attr[*npar], 0, 255)) - fprintf(stderr, "erresc: bad fgcolor %d\n", attr[*npar]); - else - idx = attr[*npar]; - break; - case 0: /* implemented defined (only foreground) */ - case 1: /* transparent */ - case 3: /* direct color in CMY space */ - case 4: /* direct color in CMYK space */ - default: - fprintf(stderr, - "erresc(38): gfx attr %d unknown\n", attr[*npar]); - break; - } - - return idx; -} - -void -tsetattr(const int *attr, int l) -{ - int i; - int32_t idx; - - for (i = 0; i < l; i++) { - switch (attr[i]) { - case 0: - term.c.attr.mode &= ~( - ATTR_BOLD | - ATTR_FAINT | - ATTR_ITALIC | - ATTR_UNDERLINE | - ATTR_BLINK | - ATTR_REVERSE | - ATTR_INVISIBLE | - ATTR_STRUCK ); - term.c.attr.fg = defaultfg; - term.c.attr.bg = defaultbg; - term.c.attr.ustyle = -1; - term.c.attr.ucolor[0] = -1; - term.c.attr.ucolor[1] = -1; - term.c.attr.ucolor[2] = -1; - break; - case 1: - term.c.attr.mode |= ATTR_BOLD; - break; - case 2: - term.c.attr.mode |= ATTR_FAINT; - break; - case 3: - term.c.attr.mode |= ATTR_ITALIC; - break; - case 4: - term.c.attr.ustyle = csiescseq.carg[i][0]; - if (term.c.attr.ustyle != 0) - term.c.attr.mode |= ATTR_UNDERLINE; - else - term.c.attr.mode &= ~ATTR_UNDERLINE; - term.c.attr.mode ^= ATTR_DIRTYUNDERLINE; - break; - case 5: /* slow blink */ - /* FALLTHROUGH */ - case 6: /* rapid blink */ - term.c.attr.mode |= ATTR_BLINK; - break; - case 7: - term.c.attr.mode |= ATTR_REVERSE; - break; - case 8: - term.c.attr.mode |= ATTR_INVISIBLE; - break; - case 9: - term.c.attr.mode |= ATTR_STRUCK; - break; - case 22: - term.c.attr.mode &= ~(ATTR_BOLD | ATTR_FAINT); - break; - case 23: - term.c.attr.mode &= ~ATTR_ITALIC; - break; - case 24: - term.c.attr.mode &= ~ATTR_UNDERLINE; - break; - case 25: - term.c.attr.mode &= ~ATTR_BLINK; - break; - case 27: - term.c.attr.mode &= ~ATTR_REVERSE; - break; - case 28: - term.c.attr.mode &= ~ATTR_INVISIBLE; - break; - case 29: - term.c.attr.mode &= ~ATTR_STRUCK; - break; - case 38: - if ((idx = tdefcolor(attr, &i, l)) >= 0) - term.c.attr.fg = idx; - break; - case 39: /* set foreground color to default */ - term.c.attr.fg = defaultfg; - break; - case 48: - if ((idx = tdefcolor(attr, &i, l)) >= 0) - term.c.attr.bg = idx; - break; - case 49: /* set background color to default */ - term.c.attr.bg = defaultbg; - break; - case 58: - term.c.attr.ucolor[0] = csiescseq.carg[i][1]; - term.c.attr.ucolor[1] = csiescseq.carg[i][2]; - term.c.attr.ucolor[2] = csiescseq.carg[i][3]; - term.c.attr.mode ^= ATTR_DIRTYUNDERLINE; - break; - case 59: - term.c.attr.ucolor[0] = -1; - term.c.attr.ucolor[1] = -1; - term.c.attr.ucolor[2] = -1; - term.c.attr.mode ^= ATTR_DIRTYUNDERLINE; - break; - default: - if (BETWEEN(attr[i], 30, 37)) { - term.c.attr.fg = attr[i] - 30; - } else if (BETWEEN(attr[i], 40, 47)) { - term.c.attr.bg = attr[i] - 40; - } else if (BETWEEN(attr[i], 90, 97)) { - term.c.attr.fg = attr[i] - 90 + 8; - } else if (BETWEEN(attr[i], 100, 107)) { - term.c.attr.bg = attr[i] - 100 + 8; - } else { - fprintf(stderr, - "erresc(default): gfx attr %d unknown\n", - attr[i]); - csidump(); - } - break; - } - } -} - -void -tsetscroll(int t, int b) -{ - int temp; - - LIMIT(t, 0, term.row-1); - LIMIT(b, 0, term.row-1); - if (t > b) { - temp = t; - t = b; - b = temp; - } - term.top = t; - term.bot = b; -} - -void -tsetmode(int priv, int set, const int *args, int narg) -{ - const int *lim; - - for (lim = args + narg; args < lim; ++args) { - if (priv) { - switch (*args) { - case 1: /* DECCKM -- Cursor key */ - xsetmode(set, MODE_APPCURSOR); - break; - case 5: /* DECSCNM -- Reverse video */ - xsetmode(set, MODE_REVERSE); - break; - case 6: /* DECOM -- Origin */ - MODBIT(term.c.state, set, CURSOR_ORIGIN); - tmoveato(0, 0); - break; - case 7: /* DECAWM -- Auto wrap */ - MODBIT(term.mode, set, MODE_WRAP); - break; - case 0: /* Error (IGNORED) */ - case 2: /* DECANM -- ANSI/VT52 (IGNORED) */ - case 3: /* DECCOLM -- Column (IGNORED) */ - case 4: /* DECSCLM -- Scroll (IGNORED) */ - case 8: /* DECARM -- Auto repeat (IGNORED) */ - case 18: /* DECPFF -- Printer feed (IGNORED) */ - case 19: /* DECPEX -- Printer extent (IGNORED) */ - case 42: /* DECNRCM -- National characters (IGNORED) */ - case 12: /* att610 -- Start blinking cursor (IGNORED) */ - break; - case 25: /* DECTCEM -- Text Cursor Enable Mode */ - xsetmode(!set, MODE_HIDE); - break; - case 9: /* X10 mouse compatibility mode */ - xsetpointermotion(0); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEX10); - break; - case 1000: /* 1000: report button press */ - xsetpointermotion(0); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEBTN); - break; - case 1002: /* 1002: report motion on button press */ - xsetpointermotion(0); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEMOTION); - break; - case 1003: /* 1003: enable all mouse motions */ - xsetpointermotion(set); - xsetmode(0, MODE_MOUSE); - xsetmode(set, MODE_MOUSEMANY); - break; - case 1004: /* 1004: send focus events to tty */ - xsetmode(set, MODE_FOCUS); - break; - case 1006: /* 1006: extended reporting mode */ - xsetmode(set, MODE_MOUSESGR); - break; - case 1034: /* 1034: enable 8-bit mode for keyboard input */ - xsetmode(set, MODE_8BIT); - break; - case 1049: /* swap screen & set/restore cursor as xterm */ - if (!allowaltscreen) - break; - tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); - /* FALLTHROUGH */ - case 47: /* swap screen buffer */ - case 1047: /* swap screen buffer */ - if (!allowaltscreen) - break; - if (set) - tloadaltscreen(*args == 1049, *args == 1049); - else - tloaddefscreen(*args == 1047, *args == 1049); - break; - /* FALLTHROUGH */ - case 1048: /* save/restore cursor (like DECSC/DECRC) */ - if (!allowaltscreen) - break; - tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD); - break; - case 2004: /* 2004: bracketed paste mode */ - xsetmode(set, MODE_BRCKTPASTE); - break; - /* Not implemented mouse modes. See comments there. */ - case 1001: /* mouse highlight mode; can hang the - terminal by design when implemented. */ - case 1005: /* UTF-8 mouse mode; will confuse - applications not supporting UTF-8 - and luit. */ - case 1015: /* urxvt mangled mouse mode; incompatible - and can be mistaken for other control - codes. */ - break; - default: - fprintf(stderr, - "erresc: unknown private set/reset mode %d\n", - *args); - break; - } - } else { - switch (*args) { - case 0: /* Error (IGNORED) */ - break; - case 2: - xsetmode(set, MODE_KBDLOCK); - break; - case 4: /* IRM -- Insertion-replacement */ - MODBIT(term.mode, set, MODE_INSERT); - break; - case 12: /* SRM -- Send/Receive */ - MODBIT(term.mode, !set, MODE_ECHO); - break; - case 20: /* LNM -- Linefeed/new line */ - MODBIT(term.mode, set, MODE_CRLF); - break; - default: - fprintf(stderr, - "erresc: unknown set/reset mode %d\n", - *args); - break; - } - } - } -} - -void -csihandle(void) -{ - char buf[40]; - int n, x; - - switch (csiescseq.mode[0]) { - default: - unknown: - fprintf(stderr, "erresc: unknown csi "); - csidump(); - /* die(""); */ - break; - case '@': /* ICH -- Insert <n> blank char */ - DEFAULT(csiescseq.arg[0], 1); - tinsertblank(csiescseq.arg[0]); - break; - case 'A': /* CUU -- Cursor <n> Up */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x, term.c.y-csiescseq.arg[0]); - break; - case 'B': /* CUD -- Cursor <n> Down */ - case 'e': /* VPR --Cursor <n> Down */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x, term.c.y+csiescseq.arg[0]); - break; - case 'i': /* MC -- Media Copy */ - switch (csiescseq.arg[0]) { - case 0: - tdump(); - break; - case 1: - tdumpline(term.c.y); - break; - case 2: - tdumpsel(); - break; - case 4: - term.mode &= ~MODE_PRINT; - break; - case 5: - term.mode |= MODE_PRINT; - break; - } - break; - case 'c': /* DA -- Device Attributes */ - if (csiescseq.arg[0] == 0) - ttywrite(vtiden, strlen(vtiden), 0); - break; - case 'b': /* REP -- if last char is printable print it <n> more times */ - LIMIT(csiescseq.arg[0], 1, 65535); - if (term.lastc) - while (csiescseq.arg[0]-- > 0) - tputc(term.lastc); - break; - case 'C': /* CUF -- Cursor <n> Forward */ - case 'a': /* HPR -- Cursor <n> Forward */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x+csiescseq.arg[0], term.c.y); - break; - case 'D': /* CUB -- Cursor <n> Backward */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(term.c.x-csiescseq.arg[0], term.c.y); - break; - case 'E': /* CNL -- Cursor <n> Down and first col */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(0, term.c.y+csiescseq.arg[0]); - break; - case 'F': /* CPL -- Cursor <n> Up and first col */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(0, term.c.y-csiescseq.arg[0]); - break; - case 'g': /* TBC -- Tabulation clear */ - switch (csiescseq.arg[0]) { - case 0: /* clear current tab stop */ - term.tabs[term.c.x] = 0; - break; - case 3: /* clear all the tabs */ - memset(term.tabs, 0, term.col * sizeof(*term.tabs)); - break; - default: - goto unknown; - } - break; - case 'G': /* CHA -- Move to <col> */ - case '`': /* HPA */ - DEFAULT(csiescseq.arg[0], 1); - tmoveto(csiescseq.arg[0]-1, term.c.y); - break; - case 'H': /* CUP -- Move to <row> <col> */ - case 'f': /* HVP */ - DEFAULT(csiescseq.arg[0], 1); - DEFAULT(csiescseq.arg[1], 1); - tmoveato(csiescseq.arg[1]-1, csiescseq.arg[0]-1); - break; - case 'I': /* CHT -- Cursor Forward Tabulation <n> tab stops */ - DEFAULT(csiescseq.arg[0], 1); - tputtab(csiescseq.arg[0]); - break; - case 'J': /* ED -- Clear screen */ - switch (csiescseq.arg[0]) { - case 0: /* below */ - tclearregion(term.c.x, term.c.y, term.col-1, term.c.y, 1); - if (term.c.y < term.row-1) { - tclearregion(0, term.c.y+1, term.col-1, term.row-1, 1); - } - break; - case 1: /* above */ - if (term.c.y >= 1) - tclearregion(0, 0, term.col-1, term.c.y-1, 1); - tclearregion(0, term.c.y, term.c.x, term.c.y, 1); - break; - case 2: /* all */ - if (IS_SET(MODE_ALTSCREEN)) { - tclearregion(0, 0, term.col-1, term.row-1, 1); - break; - } - /* vte does this: - tscrollup(0, term.row-1, term.row, SCROLL_SAVEHIST); */ - - /* alacritty does this: */ - for (n = term.row-1; n >= 0 && tlinelen(term.line[n]) == 0; n--); - if (n >= 0) - tscrollup(0, term.row-1, n+1, SCROLL_SAVEHIST); - tscrollup(0, term.row-1, term.row-n-1, SCROLL_NOSAVEHIST); - break; - default: - goto unknown; - } - break; - case 'K': /* EL -- Clear line */ - switch (csiescseq.arg[0]) { - case 0: /* right */ - tclearregion(term.c.x, term.c.y, term.col-1, term.c.y, 1); - break; - case 1: /* left */ - tclearregion(0, term.c.y, term.c.x, term.c.y, 1); - break; - case 2: /* all */ - tclearregion(0, term.c.y, term.col-1, term.c.y, 1); - break; - } - break; - case 'S': /* SU -- Scroll <n> line up */ - if (csiescseq.priv) break; - DEFAULT(csiescseq.arg[0], 1); - /* xterm, urxvt, alacritty save this in history */ - tscrollup(term.top, term.bot, csiescseq.arg[0], SCROLL_SAVEHIST); - break; - case 'T': /* SD -- Scroll <n> line down */ - DEFAULT(csiescseq.arg[0], 1); - tscrolldown(term.top, csiescseq.arg[0]); - break; - case 'L': /* IL -- Insert <n> blank lines */ - DEFAULT(csiescseq.arg[0], 1); - tinsertblankline(csiescseq.arg[0]); - break; - case 'l': /* RM -- Reset Mode */ - tsetmode(csiescseq.priv, 0, csiescseq.arg, csiescseq.narg); - break; - case 'M': /* DL -- Delete <n> lines */ - DEFAULT(csiescseq.arg[0], 1); - tdeleteline(csiescseq.arg[0]); - break; - case 'X': /* ECH -- Erase <n> char */ - if (csiescseq.arg[0] < 0) - return; - DEFAULT(csiescseq.arg[0], 1); - x = MIN(term.c.x + csiescseq.arg[0], term.col) - 1; - tclearregion(term.c.x, term.c.y, x, term.c.y, 1); - break; - case 'P': /* DCH -- Delete <n> char */ - DEFAULT(csiescseq.arg[0], 1); - tdeletechar(csiescseq.arg[0]); - break; - case 'Z': /* CBT -- Cursor Backward Tabulation <n> tab stops */ - DEFAULT(csiescseq.arg[0], 1); - tputtab(-csiescseq.arg[0]); - break; - case 'd': /* VPA -- Move to <row> */ - DEFAULT(csiescseq.arg[0], 1); - tmoveato(term.c.x, csiescseq.arg[0]-1); - break; - case 'h': /* SM -- Set terminal mode */ - tsetmode(csiescseq.priv, 1, csiescseq.arg, csiescseq.narg); - break; - case 'm': /* SGR -- Terminal attribute (color) */ - tsetattr(csiescseq.arg, csiescseq.narg); - break; - case 'n': /* DSR -- Device Status Report */ - switch (csiescseq.arg[0]) { - case 5: /* Status Report "OK" `0n` */ - ttywrite("\033[0n", sizeof("\033[0n") - 1, 0); - break; - case 6: /* Report Cursor Position (CPR) "<row>;<column>R" */ - n = snprintf(buf, sizeof(buf), "\033[%i;%iR", - term.c.y+1, term.c.x+1); - ttywrite(buf, n, 0); - break; - default: - goto unknown; - } - break; - case 'r': /* DECSTBM -- Set Scrolling Region */ - if (csiescseq.priv) { - goto unknown; - } else { - DEFAULT(csiescseq.arg[0], 1); - DEFAULT(csiescseq.arg[1], term.row); - tsetscroll(csiescseq.arg[0]-1, csiescseq.arg[1]-1); - tmoveato(0, 0); - } - break; - case 's': /* DECSC -- Save cursor position (ANSI.SYS) */ - tcursor(CURSOR_SAVE); - break; - case 'u': /* DECRC -- Restore cursor position (ANSI.SYS) */ - if (csiescseq.priv) { - goto unknown; - } else { - tcursor(CURSOR_LOAD); - } - break; - case ' ': - switch (csiescseq.mode[1]) { - case 'q': /* DECSCUSR -- Set Cursor Style */ - if (xsetcursor(csiescseq.arg[0])) - goto unknown; - break; - default: - goto unknown; - } - break; - } -} - -void -csidump(void) -{ - size_t i; - uint c; - - fprintf(stderr, "ESC["); - for (i = 0; i < csiescseq.len; i++) { - c = csiescseq.buf[i] & 0xff; - if (isprint(c)) { - putc(c, stderr); - } else if (c == '\n') { - fprintf(stderr, "(\\n)"); - } else if (c == '\r') { - fprintf(stderr, "(\\r)"); - } else if (c == 0x1b) { - fprintf(stderr, "(\\e)"); - } else { - fprintf(stderr, "(%02x)", c); - } - } - putc('\n', stderr); -} - -void -csireset(void) -{ - memset(&csiescseq, 0, sizeof(csiescseq)); -} - -void -osc_color_response(int num, int index, int is_osc4) -{ - int n; - char buf[32]; - unsigned char r, g, b; - - if (xgetcolor(is_osc4 ? num : index, &r, &g, &b)) { - fprintf(stderr, "erresc: failed to fetch %s color %d\n", - is_osc4 ? "osc4" : "osc", - is_osc4 ? num : index); - return; - } - - n = snprintf(buf, sizeof buf, "\033]%s%d;rgb:%02x%02x/%02x%02x/%02x%02x\007", - is_osc4 ? "4;" : "", num, r, r, g, g, b, b); - if (n < 0 || n >= sizeof(buf)) { - fprintf(stderr, "error: %s while printing %s response\n", - n < 0 ? "snprintf failed" : "truncation occurred", - is_osc4 ? "osc4" : "osc"); - } else { - ttywrite(buf, n, 1); - } -} - -void -strhandle(void) -{ - char *p = NULL, *dec; - int j, narg, par; - const struct { int idx; char *str; } osc_table[] = { - { defaultfg, "foreground" }, - { defaultbg, "background" }, - { defaultcs, "cursor" } - }; - - term.esc &= ~(ESC_STR_END|ESC_STR); - strparse(); - par = (narg = strescseq.narg) ? atoi(strescseq.args[0]) : 0; - - switch (strescseq.type) { - case ']': /* OSC -- Operating System Command */ - switch (par) { - case 0: - if (narg > 1) { - xsettitle(strescseq.args[1]); - xseticontitle(strescseq.args[1]); - } - return; - case 1: - if (narg > 1) - xseticontitle(strescseq.args[1]); - return; - case 2: - if (narg > 1) - xsettitle(strescseq.args[1]); - return; - case 52: /* manipulate selection data */ - if (narg > 2 && allowwindowops) { - dec = base64dec(strescseq.args[2]); - if (dec) { - xsetsel(dec); - xclipcopy(); - } else { - fprintf(stderr, "erresc: invalid base64\n"); - } - } - return; - case 10: /* set dynamic VT100 text foreground color */ - case 11: /* set dynamic VT100 text background color */ - case 12: /* set dynamic text cursor color */ - if (narg < 2) - break; - p = strescseq.args[1]; - if ((j = par - 10) < 0 || j >= LEN(osc_table)) - break; /* shouldn't be possible */ - - if (!strcmp(p, "?")) { - osc_color_response(par, osc_table[j].idx, 0); - } else if (xsetcolorname(osc_table[j].idx, p)) { - fprintf(stderr, "erresc: invalid %s color: %s\n", - osc_table[j].str, p); - } else { - tfulldirt(); - } - return; - case 4: /* color set */ - if (narg < 3) - break; - p = strescseq.args[2]; - /* FALLTHROUGH */ - case 104: /* color reset */ - j = (narg > 1) ? atoi(strescseq.args[1]) : -1; - - if (p && !strcmp(p, "?")) { - osc_color_response(j, 0, 1); - } else if (xsetcolorname(j, p)) { - if (par == 104 && narg <= 1) { - xloadcols(); - return; /* color reset without parameter */ - } - fprintf(stderr, "erresc: invalid color j=%d, p=%s\n", - j, p ? p : "(null)"); - } else { - /* - * TODO if defaultbg color is changed, borders - * are dirty - */ - tfulldirt(); - } - return; - case 110: /* reset dynamic VT100 text foreground color */ - case 111: /* reset dynamic VT100 text background color */ - case 112: /* reset dynamic text cursor color */ - if (narg != 1) - break; - if ((j = par - 110) < 0 || j >= LEN(osc_table)) - break; /* shouldn't be possible */ - if (xsetcolorname(osc_table[j].idx, NULL)) { - fprintf(stderr, "erresc: %s color not found\n", osc_table[j].str); - } else { - tfulldirt(); - } - return; - } - break; - case 'k': /* old title set compatibility */ - xsettitle(strescseq.args[0]); - return; - case 'P': /* DCS -- Device Control String */ - case '_': /* APC -- Application Program Command */ - case '^': /* PM -- Privacy Message */ - return; - } - - fprintf(stderr, "erresc: unknown str "); - strdump(); -} - -void -strparse(void) -{ - int c; - char *p = strescseq.buf; - - strescseq.narg = 0; - strescseq.buf[strescseq.len] = '\0'; - - if (*p == '\0') - return; - - while (strescseq.narg < STR_ARG_SIZ) { - strescseq.args[strescseq.narg++] = p; - while ((c = *p) != ';' && c != '\0') - ++p; - if (c == '\0') - return; - *p++ = '\0'; - } -} - -void -strdump(void) -{ - size_t i; - uint c; - - fprintf(stderr, "ESC%c", strescseq.type); - for (i = 0; i < strescseq.len; i++) { - c = strescseq.buf[i] & 0xff; - if (c == '\0') { - putc('\n', stderr); - return; - } else if (isprint(c)) { - putc(c, stderr); - } else if (c == '\n') { - fprintf(stderr, "(\\n)"); - } else if (c == '\r') { - fprintf(stderr, "(\\r)"); - } else if (c == 0x1b) { - fprintf(stderr, "(\\e)"); - } else { - fprintf(stderr, "(%02x)", c); - } - } - fprintf(stderr, "ESC\\\n"); -} - -void -strreset(void) -{ - strescseq = (STREscape){ - .buf = xrealloc(strescseq.buf, STR_BUF_SIZ), - .siz = STR_BUF_SIZ, - }; -} - -void -sendbreak(const Arg *arg) -{ - if (tcsendbreak(cmdfd, 0)) - perror("Error sending break"); -} - -void -tprinter(char *s, size_t len) -{ - if (iofd != -1 && xwrite(iofd, s, len) < 0) { - perror("Error writing to output file"); - close(iofd); - iofd = -1; - } -} - -void -toggleprinter(const Arg *arg) -{ - term.mode ^= MODE_PRINT; -} - -void -printscreen(const Arg *arg) -{ - tdump(); -} - -void -printsel(const Arg *arg) -{ - tdumpsel(); -} - -void -tdumpsel(void) -{ - char *ptr; - - if ((ptr = getsel())) { - tprinter(ptr, strlen(ptr)); - free(ptr); - } -} - -void -tdumpline(int n) -{ - char str[(term.col + 1) * UTF_SIZ]; - tprinter(str, tgetline(str, &term.line[n][0])); -} - -void -tdump(void) -{ - int i; - - for (i = 0; i < term.row; ++i) - tdumpline(i); -} - -void -tputtab(int n) -{ - uint x = term.c.x; - - if (n > 0) { - while (x < term.col && n--) - for (++x; x < term.col && !term.tabs[x]; ++x) - /* nothing */ ; - } else if (n < 0) { - while (x > 0 && n++) - for (--x; x > 0 && !term.tabs[x]; --x) - /* nothing */ ; - } - term.c.x = LIMIT(x, 0, term.col-1); -} - -void -tdefutf8(char ascii) -{ - if (ascii == 'G') - term.mode |= MODE_UTF8; - else if (ascii == '@') - term.mode &= ~MODE_UTF8; -} - -void -tdeftran(char ascii) -{ - static char cs[] = "0B"; - static int vcs[] = {CS_GRAPHIC0, CS_USA}; - char *p; - - if ((p = strchr(cs, ascii)) == NULL) { - fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii); - } else { - term.trantbl[term.icharset] = vcs[p - cs]; - } -} - -void -tdectest(char c) -{ - int x, y; - - if (c == '8') { /* DEC screen alignment test. */ - for (x = 0; x < term.col; ++x) { - for (y = 0; y < term.row; ++y) - tsetchar('E', &term.c.attr, x, y); - } - } -} - -void -tstrsequence(uchar c) -{ - switch (c) { - case 0x90: /* DCS -- Device Control String */ - c = 'P'; - break; - case 0x9f: /* APC -- Application Program Command */ - c = '_'; - break; - case 0x9e: /* PM -- Privacy Message */ - c = '^'; - break; - case 0x9d: /* OSC -- Operating System Command */ - c = ']'; - break; - } - strreset(); - strescseq.type = c; - term.esc |= ESC_STR; -} - -void -tcontrolcode(uchar ascii) -{ - switch (ascii) { - case '\t': /* HT */ - tputtab(1); - return; - case '\b': /* BS */ - tmoveto(term.c.x-1, term.c.y); - return; - case '\r': /* CR */ - tmoveto(0, term.c.y); - return; - case '\f': /* LF */ - case '\v': /* VT */ - case '\n': /* LF */ - /* go to first col if the mode is set */ - tnewline(IS_SET(MODE_CRLF)); - return; - case '\a': /* BEL */ - if (term.esc & ESC_STR_END) { - /* backwards compatibility to xterm */ - strhandle(); - } else { - xbell(); - } - break; - case '\033': /* ESC */ - csireset(); - term.esc &= ~(ESC_CSI|ESC_ALTCHARSET|ESC_TEST); - term.esc |= ESC_START; - return; - case '\016': /* SO (LS1 -- Locking shift 1) */ - case '\017': /* SI (LS0 -- Locking shift 0) */ - term.charset = 1 - (ascii - '\016'); - return; - case '\032': /* SUB */ - tsetchar('?', &term.c.attr, term.c.x, term.c.y); - /* FALLTHROUGH */ - case '\030': /* CAN */ - csireset(); - break; - case '\005': /* ENQ (IGNORED) */ - case '\000': /* NUL (IGNORED) */ - case '\021': /* XON (IGNORED) */ - case '\023': /* XOFF (IGNORED) */ - case 0177: /* DEL (IGNORED) */ - return; - case 0x80: /* TODO: PAD */ - case 0x81: /* TODO: HOP */ - case 0x82: /* TODO: BPH */ - case 0x83: /* TODO: NBH */ - case 0x84: /* TODO: IND */ - break; - case 0x85: /* NEL -- Next line */ - tnewline(1); /* always go to first col */ - break; - case 0x86: /* TODO: SSA */ - case 0x87: /* TODO: ESA */ - break; - case 0x88: /* HTS -- Horizontal tab stop */ - term.tabs[term.c.x] = 1; - break; - case 0x89: /* TODO: HTJ */ - case 0x8a: /* TODO: VTS */ - case 0x8b: /* TODO: PLD */ - case 0x8c: /* TODO: PLU */ - case 0x8d: /* TODO: RI */ - case 0x8e: /* TODO: SS2 */ - case 0x8f: /* TODO: SS3 */ - case 0x91: /* TODO: PU1 */ - case 0x92: /* TODO: PU2 */ - case 0x93: /* TODO: STS */ - case 0x94: /* TODO: CCH */ - case 0x95: /* TODO: MW */ - case 0x96: /* TODO: SPA */ - case 0x97: /* TODO: EPA */ - case 0x98: /* TODO: SOS */ - case 0x99: /* TODO: SGCI */ - break; - case 0x9a: /* DECID -- Identify Terminal */ - ttywrite(vtiden, strlen(vtiden), 0); - break; - case 0x9b: /* TODO: CSI */ - case 0x9c: /* TODO: ST */ - break; - case 0x90: /* DCS -- Device Control String */ - case 0x9d: /* OSC -- Operating System Command */ - case 0x9e: /* PM -- Privacy Message */ - case 0x9f: /* APC -- Application Program Command */ - tstrsequence(ascii); - return; - } - /* only CAN, SUB, \a and C1 chars interrupt a sequence */ - term.esc &= ~(ESC_STR_END|ESC_STR); -} - -/* - * returns 1 when the sequence is finished and it hasn't to read - * more characters for this sequence, otherwise 0 - */ -int -eschandle(uchar ascii) -{ - switch (ascii) { - case '[': - term.esc |= ESC_CSI; - return 0; - case '#': - term.esc |= ESC_TEST; - return 0; - case '%': - term.esc |= ESC_UTF8; - return 0; - case 'P': /* DCS -- Device Control String */ - case '_': /* APC -- Application Program Command */ - case '^': /* PM -- Privacy Message */ - case ']': /* OSC -- Operating System Command */ - case 'k': /* old title set compatibility */ - tstrsequence(ascii); - return 0; - case 'n': /* LS2 -- Locking shift 2 */ - case 'o': /* LS3 -- Locking shift 3 */ - term.charset = 2 + (ascii - 'n'); - break; - case '(': /* GZD4 -- set primary charset G0 */ - case ')': /* G1D4 -- set secondary charset G1 */ - case '*': /* G2D4 -- set tertiary charset G2 */ - case '+': /* G3D4 -- set quaternary charset G3 */ - term.icharset = ascii - '('; - term.esc |= ESC_ALTCHARSET; - return 0; - case 'D': /* IND -- Linefeed */ - if (term.c.y == term.bot) { - tscrollup(term.top, term.bot, 1, SCROLL_SAVEHIST); - } else { - tmoveto(term.c.x, term.c.y+1); - } - break; - case 'E': /* NEL -- Next line */ - tnewline(1); /* always go to first col */ - break; - case 'H': /* HTS -- Horizontal tab stop */ - term.tabs[term.c.x] = 1; - break; - case 'M': /* RI -- Reverse index */ - if (term.c.y == term.top) { - tscrolldown(term.top, 1); - } else { - tmoveto(term.c.x, term.c.y-1); - } - break; - case 'Z': /* DECID -- Identify Terminal */ - ttywrite(vtiden, strlen(vtiden), 0); - break; - case 'c': /* RIS -- Reset to initial state */ - treset(); - resettitle(); - xloadcols(); - xsetmode(0, MODE_HIDE); - break; - case '=': /* DECPAM -- Application keypad */ - xsetmode(1, MODE_APPKEYPAD); - break; - case '>': /* DECPNM -- Normal keypad */ - xsetmode(0, MODE_APPKEYPAD); - break; - case '7': /* DECSC -- Save Cursor */ - tcursor(CURSOR_SAVE); - break; - case '8': /* DECRC -- Restore Cursor */ - tcursor(CURSOR_LOAD); - break; - case '\\': /* ST -- String Terminator */ - if (term.esc & ESC_STR_END) - strhandle(); - break; - default: - fprintf(stderr, "erresc: unknown sequence ESC 0x%02X '%c'\n", - (uchar) ascii, isprint(ascii)? ascii:'.'); - break; - } - return 1; -} - -void -tputc(Rune u) -{ - char c[UTF_SIZ]; - int control; - int width, len; - Glyph *gp; - - control = ISCONTROL(u); - if (u < 127 || !IS_SET(MODE_UTF8)) { - c[0] = u; - width = len = 1; - } else { - len = utf8encode(u, c); - if (!control && (width = wcwidth(u)) == -1) - width = 1; - } - - if (IS_SET(MODE_PRINT)) - tprinter(c, len); - - /* - * STR sequence must be checked before anything else - * because it uses all following characters until it - * receives a ESC, a SUB, a ST or any other C1 control - * character. - */ - if (term.esc & ESC_STR) { - if (u == '\a' || u == 030 || u == 032 || u == 033 || - ISCONTROLC1(u)) { - term.esc &= ~(ESC_START|ESC_STR); - term.esc |= ESC_STR_END; - goto check_control_code; - } - - if (strescseq.len+len >= strescseq.siz) { - /* - * Here is a bug in terminals. If the user never sends - * some code to stop the str or esc command, then st - * will stop responding. But this is better than - * silently failing with unknown characters. At least - * then users will report back. - * - * In the case users ever get fixed, here is the code: - */ - /* - * term.esc = 0; - * strhandle(); - */ - if (strescseq.siz > (SIZE_MAX - UTF_SIZ) / 2) - return; - strescseq.siz *= 2; - strescseq.buf = xrealloc(strescseq.buf, strescseq.siz); - } - - memmove(&strescseq.buf[strescseq.len], c, len); - strescseq.len += len; - return; - } - -check_control_code: - /* - * Actions of control codes must be performed as soon they arrive - * because they can be embedded inside a control sequence, and - * they must not cause conflicts with sequences. - */ - if (control) { - /* in UTF-8 mode ignore handling C1 control characters */ - if (IS_SET(MODE_UTF8) && ISCONTROLC1(u)) - return; - tcontrolcode(u); - /* - * control codes are not shown ever - */ - if (!term.esc) - term.lastc = 0; - return; - } else if (term.esc & ESC_START) { - if (term.esc & ESC_CSI) { - csiescseq.buf[csiescseq.len++] = u; - if (BETWEEN(u, 0x40, 0x7E) - || csiescseq.len >= \ - sizeof(csiescseq.buf)-1) { - term.esc = 0; - csiparse(); - csihandle(); - } - return; - } else if (term.esc & ESC_UTF8) { - tdefutf8(u); - } else if (term.esc & ESC_ALTCHARSET) { - tdeftran(u); - } else if (term.esc & ESC_TEST) { - tdectest(u); - } else { - if (!eschandle(u)) - return; - /* sequence already finished */ - } - term.esc = 0; - /* - * All characters which form part of a sequence are not - * printed - */ - return; - } - - /* selected() takes relative coordinates */ - if (selected(term.c.x + term.scr, term.c.y + term.scr)) - selclear(); - - gp = &term.line[term.c.y][term.c.x]; - if (IS_SET(MODE_WRAP) && (term.c.state & CURSOR_WRAPNEXT)) { - gp->mode |= ATTR_WRAP; - tnewline(1); - gp = &term.line[term.c.y][term.c.x]; - } - - if (IS_SET(MODE_INSERT) && term.c.x+width < term.col) { - memmove(gp+width, gp, (term.col - term.c.x - width) * sizeof(Glyph)); - gp->mode &= ~ATTR_WIDE; - } - - if (term.c.x+width > term.col) { - if (IS_SET(MODE_WRAP)) - tnewline(1); - else - tmoveto(term.col - width, term.c.y); - gp = &term.line[term.c.y][term.c.x]; - } - - tsetchar(u, &term.c.attr, term.c.x, term.c.y); - term.lastc = u; - - if (width == 2) { - gp->mode |= ATTR_WIDE; - if (term.c.x+1 < term.col) { - if (gp[1].mode == ATTR_WIDE && term.c.x+2 < term.col) { - gp[2].u = ' '; - gp[2].mode &= ~ATTR_WDUMMY; - } - gp[1].u = '\0'; - gp[1].mode = ATTR_WDUMMY; - } - } - if (term.c.x+width < term.col) { - tmoveto(term.c.x+width, term.c.y); - } else { - term.wrapcwidth[IS_SET(MODE_ALTSCREEN)] = width; - term.c.state |= CURSOR_WRAPNEXT; - } -} - -int -twrite(const char *buf, int buflen, int show_ctrl) -{ - int charsize; - Rune u; - int n; - - for (n = 0; n < buflen; n += charsize) { - if (IS_SET(MODE_UTF8)) { - /* process a complete utf8 char */ - charsize = utf8decode(buf + n, &u, buflen - n); - if (charsize == 0) - break; - } else { - u = buf[n] & 0xFF; - charsize = 1; - } - if (show_ctrl && ISCONTROL(u)) { - if (u & 0x80) { - u &= 0x7f; - tputc('^'); - tputc('['); - } else if (u != '\n' && u != '\r' && u != '\t') { - u ^= 0x40; - tputc('^'); - } - } - tputc(u); - } - return n; -} - -void -rscrolldown(int n) -{ - int i; - Line temp; - - /* can never be true as of now - if (IS_SET(MODE_ALTSCREEN)) - return; */ - - if ((n = MIN(n, term.histf)) <= 0) - return; - - for (i = term.c.y + n; i >= n; i--) { - temp = term.line[i]; - term.line[i] = term.line[i-n]; - term.line[i-n] = temp; - } - for (/*i = n - 1 */; i >= 0; i--) { - temp = term.line[i]; - term.line[i] = term.hist[term.histi]; - term.hist[term.histi] = temp; - term.histi = (term.histi - 1 + HISTSIZE) % HISTSIZE; - } - term.c.y += n; - term.histf -= n; - if ((i = term.scr - n) >= 0) { - term.scr = i; - } else { - term.scr = 0; - if (sel.ob.x != -1 && !sel.alt) - selmove(-i); - } -} - - - -void -tresize(int col, int row) -{ - int *bp; - - if ( row < term.row || col < term.col ) - toggle_winmode(trt_kbdselect(XK_Escape, NULL, 0)); - - /* col and row are always MAX(_, 1) - if (col < 1 || row < 1) { - fprintf(stderr, "tresize: error resizing to %dx%d\n", col, row); - return; - } */ - - term.dirty = xrealloc(term.dirty, row * sizeof(*term.dirty)); - term.tabs = xrealloc(term.tabs, col * sizeof(*term.tabs)); - if (col > term.col) { - bp = term.tabs + term.col; - memset(bp, 0, sizeof(*term.tabs) * (col - term.col)); - while (--bp > term.tabs && !*bp) - /* nothing */ ; - for (bp += tabspaces; bp < term.tabs + col; bp += tabspaces) - *bp = 1; - } - - if (IS_SET(MODE_ALTSCREEN)) - tresizealt(col, row); - else - tresizedef(col, row); -} - - -void -tresizedef(int col, int row) -{ - int i, j; - - /* return if dimensions haven't changed */ - if (term.col == col && term.row == row) { - tfulldirt(); - return; - } - if (col != term.col) { - if (!sel.alt) - selremove(); - treflow(col, row); - } else { - /* slide screen up if otherwise cursor would get out of the screen */ - if (term.c.y >= row) { - tscrollup(0, term.row - 1, term.c.y - row + 1, SCROLL_RESIZE); - term.c.y = row - 1; - } - for (i = row; i < term.row; i++) - free(term.line[i]); - - /* resize to new height */ - term.line = xrealloc(term.line, row * sizeof(Line)); - /* allocate any new rows */ - for (i = term.row; i < row; i++) { - term.line[i] = xmalloc(col * sizeof(Glyph)); - for (j = 0; j < col; j++) - tclearglyph(&term.line[i][j], 0); - } - /* scroll down as much as height has increased */ - rscrolldown(row - term.row); - } - /* update terminal size */ - term.col = col, term.row = row; - /* reset scrolling region */ - term.top = 0, term.bot = row - 1; - /* dirty all lines */ - tfulldirt(); -} - - - -void -tresizealt(int col, int row) -{ - int i, j; - - /* return if dimensions haven't changed */ - if (term.col == col && term.row == row) { - tfulldirt(); - return; - } - if (sel.alt) - selremove(); - /* slide screen up if otherwise cursor would get out of the screen */ - for (i = 0; i <= term.c.y - row; i++) - free(term.line[i]); - if (i > 0) { - /* ensure that both src and dst are not NULL */ - memmove(term.line, term.line + i, row * sizeof(Line)); - term.c.y = row - 1; - } - for (i += row; i < term.row; i++) - free(term.line[i]); - /* resize to new height */ - term.line = xrealloc(term.line, row * sizeof(Line)); - /* resize to new width */ - for (i = 0; i < MIN(row, term.row); i++) { - term.line[i] = xrealloc(term.line[i], col * sizeof(Glyph)); - for (j = term.col; j < col; j++) - tclearglyph(&term.line[i][j], 0); - } - /* allocate any new rows */ - for (/*i = MIN(row, term.row) */; i < row; i++) { - term.line[i] = xmalloc(col * sizeof(Glyph)); - for (j = 0; j < col; j++) - tclearglyph(&term.line[i][j], 0); - } - /* update cursor */ - if (term.c.x >= col) { - term.c.state &= ~CURSOR_WRAPNEXT; - term.c.x = col - 1; - } else { - UPDATEWRAPNEXT(1, col); - } - /* update terminal size */ - term.col = col, term.row = row; - /* reset scrolling region */ - term.top = 0, term.bot = row - 1; - /* dirty all lines */ - tfulldirt(); -} - - - - - -void -treflow(int col, int row) -{ - int i, j; - int oce, nce, bot, scr; - int ox = 0, oy = -term.histf, nx = 0, ny = -1, len; - int cy = -1; /* proxy for new y coordinate of cursor */ - int nlines; - Line *buf, line; - - /* y coordinate of cursor line end */ - for (oce = term.c.y; oce < term.row - 1 && - tiswrapped(term.line[oce]); oce++); - - nlines = term.histf + oce + 1; - if (col < term.col) { - /* each line can take this many lines after reflow */ - j = (term.col + col - 1) / col; - nlines = j * nlines; - if (nlines > HISTSIZE + RESIZEBUFFER + row) { - nlines = HISTSIZE + RESIZEBUFFER + row; - oy = -(nlines / j - oce - 1); - } - } - buf = xmalloc(nlines * sizeof(Line)); - do { - if (!nx) - buf[++ny] = xmalloc(col * sizeof(Glyph)); - if (!ox) { - line = TLINEABS(oy); - len = tlinelen(line); - } - if (oy == term.c.y) { - if (!ox) - len = MAX(len, term.c.x + 1); - /* update cursor */ - if (cy < 0 && term.c.x - ox < col - nx) { - term.c.x = nx + term.c.x - ox, cy = ny; - UPDATEWRAPNEXT(0, col); - } - } - /* get reflowed lines in buf */ - if (col - nx > len - ox) { - memcpy(&buf[ny][nx], &line[ox], (len-ox) * sizeof(Glyph)); - nx += len - ox; - if (len == 0 || !(line[len - 1].mode & ATTR_WRAP)) { - for (j = nx; j < col; j++) - tclearglyph(&buf[ny][j], 0); - nx = 0; - } else if (nx > 0) { - buf[ny][nx - 1].mode &= ~ATTR_WRAP; - } - ox = 0, oy++; - } else if (col - nx == len - ox) { - memcpy(&buf[ny][nx], &line[ox], (col-nx) * sizeof(Glyph)); - ox = 0, oy++, nx = 0; - } else/* if (col - nx < len - ox) */ { - memcpy(&buf[ny][nx], &line[ox], (col-nx) * sizeof(Glyph)); - ox += col - nx; - buf[ny][col - 1].mode |= ATTR_WRAP; - nx = 0; - } - } while (oy <= oce); - if (nx) - for (j = nx; j < col; j++) - tclearglyph(&buf[ny][j], 0); - - /* free extra lines */ - for (i = row; i < term.row; i++) - free(term.line[i]); - /* resize to new height */ - term.line = xrealloc(term.line, row * sizeof(Line)); - - bot = MIN(ny, row - 1); - scr = MAX(row - term.row, 0); - /* update y coordinate of cursor line end */ - nce = MIN(oce + scr, bot); - /* update cursor y coordinate */ - term.c.y = nce - (ny - cy); - if (term.c.y < 0) { - j = nce, nce = MIN(nce + -term.c.y, bot); - term.c.y += nce - j; - while (term.c.y < 0) { - free(buf[ny--]); - term.c.y++; - } - } - /* allocate new rows */ - for (i = row - 1; i > nce; i--) { - term.line[i] = xmalloc(col * sizeof(Glyph)); - for (j = 0; j < col; j++) - tclearglyph(&term.line[i][j], 0); - } - /* fill visible area */ - for (/*i = nce */; i >= term.row; i--, ny--) - term.line[i] = buf[ny]; - for (/*i = term.row - 1 */; i >= 0; i--, ny--) { - free(term.line[i]); - term.line[i] = buf[ny]; - } - /* fill lines in history buffer and update term.histf */ - for (/*i = -1 */; ny >= 0 && i >= -HISTSIZE; i--, ny--) { - j = (term.histi + i + 1 + HISTSIZE) % HISTSIZE; - free(term.hist[j]); - term.hist[j] = buf[ny]; - } - term.histf = -i - 1; - term.scr = MIN(term.scr, term.histf); - /* resize rest of the history lines */ - for (/*i = -term.histf - 1 */; i >= -HISTSIZE; i--) { - j = (term.histi + i + 1 + HISTSIZE) % HISTSIZE; - term.hist[j] = xrealloc(term.hist[j], col * sizeof(Glyph)); - } - free(buf); -} - -void -resettitle(void) -{ - xsettitle(NULL); -} - -void -drawregion(int x1, int y1, int x2, int y2) -{ - int y; - - for (y = y1; y < y2; y++) { - if (!term.dirty[y]) - continue; - - term.dirty[y] = 0; - xdrawline(TLINE(y), x1, y, x2); - } -} - -void -draw(void) -{ - int cx = term.c.x, ocx = term.ocx, ocy = term.ocy; - - if (!xstartdraw()) - return; - - /* adjust cursor position */ - LIMIT(term.ocx, 0, term.col-1); - LIMIT(term.ocy, 0, term.row-1); - if (term.line[term.ocy][term.ocx].mode & ATTR_WDUMMY) - term.ocx--; - if (term.line[term.c.y][cx].mode & ATTR_WDUMMY) - cx--; - - drawregion(0, 0, term.col, term.row); - xdrawcursor(cx, term.c.y, term.line[term.c.y][cx], - term.ocx, term.ocy, term.line[term.ocy][term.ocx]); - term.ocx = cx; - term.ocy = term.c.y; - xfinishdraw(); - if (ocx != term.ocx || ocy != term.ocy) - xximspot(term.ocx, term.ocy); -} - -void -redraw(void) -{ - tfulldirt(); - draw(); -} - -void set_notifmode(int type, KeySym ksym) { - static char *lib[] = { " MOVE ", " SEL "}; - static Glyph *g, *deb, *fin; - static int col, bot; - - if ( ksym == -1 ) { - free(g); - col = term.col, bot = term.bot; - g = xmalloc(col * sizeof(Glyph)); - memcpy(g, term.line[bot], col * sizeof(Glyph)); - - } - else if ( ksym == -2 ) - memcpy(term.line[bot], g, col * sizeof(Glyph)); - - if ( type < 2 ) { - char *z = lib[type]; - for (deb = &term.line[bot][col - 6], fin = &term.line[bot][col]; deb < fin; z++, deb++) - deb->mode = ATTR_REVERSE, - deb->u = *z, - deb->fg = defaultfg, deb->bg = defaultbg; - } - else if ( type < 5 ) - memcpy(term.line[bot], g, col * sizeof(Glyph)); - else { - for (deb = &term.line[bot][0], fin = &term.line[bot][col]; deb < fin; deb++) - deb->mode = ATTR_REVERSE, - deb->u = ' ', - deb->fg = defaultfg, deb->bg = defaultbg; - term.line[bot][0].u = ksym; - } - - term.dirty[bot] = 1; - drawregion(0, bot, col, bot + 1); -} - -void select_or_drawcursor(int selectsearch_mode, int type) { - int done = 0; - - if ( selectsearch_mode & 1 ) { - selextend(term.c.x, term.c.y, type, done); - xsetsel(getsel()); - } - else - xdrawcursor(term.c.x, term.c.y, term.line[term.c.y][term.c.x], - term.ocx, term.ocy, term.line[term.ocy][term.ocx]); -} - -void search(int selectsearch_mode, Rune *target, int ptarget, int incr, int type, TCursor *cu) { - Rune *r; - int i, bound = (term.col * cu->y + cu->x) * (incr > 0) + incr; - - for (i = term.col * term.c.y + term.c.x + incr; i != bound; i += incr) { - for (r = target; r - target < ptarget; r++) { - if ( *r == term.line[(i + r - target) / term.col][(i + r - target) % term.col].u ) { - if ( r - target == ptarget - 1 ) break; - } else { - r = NULL; - break; - } - } - if ( r != NULL ) break; - } - - if ( i != bound ) { - term.c.y = i / term.col, term.c.x = i % term.col; - select_or_drawcursor(selectsearch_mode, type); - } -} - -int trt_kbdselect(KeySym ksym, char *buf, int len) { - static TCursor cu; - static Rune target[64]; - static int type = 1, ptarget, in_use; - static int sens, quant; - static char selectsearch_mode; - int i, bound, *xy; - - - if ( selectsearch_mode & 2 ) { - if ( ksym == XK_Return ) { - selectsearch_mode ^= 2; - set_notifmode(selectsearch_mode, -2); - if ( ksym == XK_Escape ) ptarget = 0; - return 0; - } - else if ( ksym == XK_BackSpace ) { - if ( !ptarget ) return 0; - term.line[term.bot][ptarget--].u = ' '; - } - else if ( len < 1 ) { - return 0; - } - else if ( ptarget == term.col || ksym == XK_Escape ) { - return 0; - } - else { - utf8decode(buf, &target[ptarget++], len); - term.line[term.bot][ptarget].u = target[ptarget - 1]; - } - - if ( ksym != XK_BackSpace ) - search(selectsearch_mode, &target[0], ptarget, sens, type, &cu); - - term.dirty[term.bot] = 1; - drawregion(0, term.bot, term.col, term.bot + 1); - return 0; - } - - switch ( ksym ) { - case -1 : - in_use = 1; - cu.x = term.c.x, cu.y = term.c.y; - set_notifmode(0, ksym); - return MODE_KBDSELECT; - case XK_s : - if ( selectsearch_mode & 1 ) - selclear(); - else - selstart(term.c.x, term.c.y, 0); - set_notifmode(selectsearch_mode ^= 1, ksym); - break; - case XK_t : - selextend(term.c.x, term.c.y, type ^= 3, i = 0); /* 2 fois */ - selextend(term.c.x, term.c.y, type, i = 0); - break; - case XK_slash : - case XK_KP_Divide : - case XK_question : - ksym &= XK_question; /* Divide to slash */ - sens = (ksym == XK_slash) ? -1 : 1; - ptarget = 0; - set_notifmode(15, ksym); - selectsearch_mode ^= 2; - break; - case XK_Escape : - if ( !in_use ) break; - selclear(); - case XK_Return : - set_notifmode(4, ksym); - term.c.x = cu.x, term.c.y = cu.y; - select_or_drawcursor(selectsearch_mode = 0, type); - in_use = quant = 0; - return MODE_KBDSELECT; - case XK_n : - case XK_N : - if ( ptarget ) - search(selectsearch_mode, &target[0], ptarget, (ksym == XK_n) ? -1 : 1, type, &cu); - break; - case XK_BackSpace : - term.c.x = 0; - select_or_drawcursor(selectsearch_mode, type); - break; - case XK_dollar : - term.c.x = term.col - 1; - select_or_drawcursor(selectsearch_mode, type); - break; - case XK_Home : - term.c.x = 0, term.c.y = 0; - select_or_drawcursor(selectsearch_mode, type); - break; - case XK_End : - term.c.x = cu.x, term.c.y = cu.y; - select_or_drawcursor(selectsearch_mode, type); - break; - case XK_Page_Up : - case XK_Page_Down : - term.c.y = (ksym == XK_Prior ) ? 0 : cu.y; - select_or_drawcursor(selectsearch_mode, type); - break; - case XK_exclam : - term.c.x = term.col >> 1; - select_or_drawcursor(selectsearch_mode, type); - break; - case XK_asterisk : - case XK_KP_Multiply : - term.c.x = term.col >> 1; - case XK_underscore : - term.c.y = cu.y >> 1; - select_or_drawcursor(selectsearch_mode, type); - break; - default : - if ( ksym >= XK_0 && ksym <= XK_9 ) { /* 0-9 keyboard */ - quant = (quant * 10) + (ksym ^ XK_0); - return 0; - } - else if ( ksym >= XK_KP_0 && ksym <= XK_KP_9 ) { /* 0-9 numpad */ - quant = (quant * 10) + (ksym ^ XK_KP_0); - return 0; - } - else if ( ksym == XK_k || ksym == XK_h ) - i = ksym & 1; - else if ( ksym == XK_l || ksym == XK_j ) - i = ((ksym & 6) | 4) >> 1; - else if ( (XK_Home & ksym) != XK_Home || (i = (ksym ^ XK_Home) - 1) > 3 ) - break; - - xy = (i & 1) ? &term.c.y : &term.c.x; - sens = (i & 2) ? 1 : -1; - bound = (i >> 1 ^ 1) ? 0 : (i ^ 3) ? term.col - 1 : term.bot; - - if ( quant == 0 ) - quant++; - - if ( *xy == bound && ((sens < 0 && bound == 0) || (sens > 0 && bound > 0)) ) - break; - - *xy += quant * sens; - if ( *xy < 0 || ( bound > 0 && *xy > bound) ) - *xy = bound; - - select_or_drawcursor(selectsearch_mode, type); - } - quant = 0; - return 0; -} diff --git a/st/st-0.9.3/st.h b/st/st-0.9.3/st.h deleted file mode 100644 index 3b2b3e1..0000000 --- a/st/st-0.9.3/st.h +++ /dev/null @@ -1,136 +0,0 @@ -/* See LICENSE for license details. */ - -#include <stdint.h> -#include <sys/types.h> - -/* macros */ -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#define MAX(a, b) ((a) < (b) ? (b) : (a)) -#define LEN(a) (sizeof(a) / sizeof(a)[0]) -#define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b)) -#define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d)) -#define DEFAULT(a, b) (a) = (a) ? (a) : (b) -#define LIMIT(x, a, b) (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x) -#define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg != (b).fg || \ - (a).bg != (b).bg) -#define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + \ - (t1.tv_nsec-t2.tv_nsec)/1E6) -#define MODBIT(x, set, bit) ((set) ? ((x) |= (bit)) : ((x) &= ~(bit))) - -#define TRUECOLOR(r,g,b) (1 << 24 | (r) << 16 | (g) << 8 | (b)) -#define IS_TRUECOL(x) (1 << 24 & (x)) - -enum glyph_attribute { - ATTR_NULL = 0, - ATTR_SET = 1 << 0, - ATTR_BOLD = 1 << 1, - ATTR_FAINT = 1 << 2, - ATTR_ITALIC = 1 << 3, - ATTR_UNDERLINE = 1 << 4, - ATTR_BLINK = 1 << 5, - ATTR_REVERSE = 1 << 6, - ATTR_INVISIBLE = 1 << 7, - ATTR_STRUCK = 1 << 8, - ATTR_WRAP = 1 << 9, - ATTR_WIDE = 1 << 10, - ATTR_WDUMMY = 1 << 11, - ATTR_SELECTED = 1 << 12, - ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, - ATTR_DIRTYUNDERLINE = 1 << 15, -}; - -enum selection_mode { - SEL_IDLE = 0, - SEL_EMPTY = 1, - SEL_READY = 2 -}; - -enum selection_type { - SEL_REGULAR = 1, - SEL_RECTANGULAR = 2 -}; - -enum selection_snap { - SNAP_WORD = 1, - SNAP_LINE = 2 -}; - -typedef unsigned char uchar; -typedef unsigned int uint; -typedef unsigned long ulong; -typedef unsigned short ushort; - -typedef uint_least32_t Rune; - -#define Glyph Glyph_ -typedef struct { - Rune u; /* character code */ - ushort mode; /* attribute flags */ - uint32_t fg; /* foreground */ - uint32_t bg; /* background */ - int ustyle; /* underline style */ - int ucolor[3]; /* underline color */ -} Glyph; - -typedef Glyph *Line; - -typedef union { - int i; - uint ui; - float f; - const void *v; - const char *s; -} Arg; - -void die(const char *, ...); -void redraw(void); -void draw(void); - -void kscrolldown(const Arg *); -void kscrollup(const Arg *); -void printscreen(const Arg *); -void printsel(const Arg *); -void sendbreak(const Arg *); -void toggleprinter(const Arg *); - -int tattrset(int); -int tisaltscr(void); -void tnew(int, int); -int tisaltscreen(void); -void tresize(int, int); -void tsetdirtattr(int); -void ttyhangup(void); -int ttynew(const char *, char *, const char *, char **); -size_t ttyread(void); -void ttyresize(int, int); -void ttywrite(const char *, size_t, int); - -void resettitle(void); - -void selclear(void); -void selinit(void); -void selstart(int, int, int); -void selextend(int, int, int, int); -int selected(int, int); -char *getsel(void); - -size_t utf8encode(Rune, char *); - -void *xmalloc(size_t); -void *xrealloc(void *, size_t); -char *xstrdup(const char *); -int trt_kbdselect(KeySym, char *, int); - -/* config.h globals */ -extern char *utmp; -extern char *scroll; -extern char *stty_args; -extern char *vtiden; -extern wchar_t *worddelimiters; -extern int allowaltscreen; -extern int allowwindowops; -extern char *termname; -extern unsigned int tabspaces; -extern unsigned int defaultfg; -extern unsigned int defaultbg; -extern unsigned int defaultcs; diff --git a/st/st-0.9.3/st.info b/st/st-0.9.3/st.info deleted file mode 100644 index 23b1875..0000000 --- a/st/st-0.9.3/st.info +++ /dev/null @@ -1,244 +0,0 @@ -st-mono| simpleterm monocolor, - Su, - acsc=+C\,D-A.B0E``aaffgghFiGjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~, - am, - bce, - bel=^G, - blink=\E[5m, - bold=\E[1m, - cbt=\E[Z, - cvvis=\E[?25h, - civis=\E[?25l, - clear=\E[H\E[2J, - cnorm=\E[?12l\E[?25h, - colors#2, - cols#80, - cr=^M, - csr=\E[%i%p1%d;%p2%dr, - cub=\E[%p1%dD, - cub1=^H, - cud1=^J, - cud=\E[%p1%dB, - cuf1=\E[C, - cuf=\E[%p1%dC, - cup=\E[%i%p1%d;%p2%dH, - cuu1=\E[A, - cuu=\E[%p1%dA, - dch=\E[%p1%dP, - dch1=\E[P, - dim=\E[2m, - dl=\E[%p1%dM, - dl1=\E[M, - ech=\E[%p1%dX, - ed=\E[J, - el=\E[K, - el1=\E[1K, - enacs=\E)0, - flash=\E[?5h$<80/>\E[?5l, - fsl=^G, - home=\E[H, - hpa=\E[%i%p1%dG, - hs, - ht=^I, - hts=\EH, - ich=\E[%p1%d@, - il1=\E[L, - il=\E[%p1%dL, - ind=^J, - indn=\E[%p1%dS, - invis=\E[8m, - is2=\E[4l\E>\E[?1034l, - it#8, - kel=\E[1;2F, - ked=\E[1;5F, - ka1=\E[1~, - ka3=\E[5~, - kc1=\E[4~, - kc3=\E[6~, - kbs=\177, - kcbt=\E[Z, - kb2=\EOu, - kcub1=\EOD, - kcud1=\EOB, - kcuf1=\EOC, - kcuu1=\EOA, - kDC=\E[3;2~, - kent=\EOM, - kEND=\E[1;2F, - kIC=\E[2;2~, - kNXT=\E[6;2~, - kPRV=\E[5;2~, - kHOM=\E[1;2H, - kLFT=\E[1;2D, - kRIT=\E[1;2C, - kind=\E[1;2B, - kri=\E[1;2A, - kclr=\E[3;5~, - kdl1=\E[3;2~, - kdch1=\E[3~, - kich1=\E[2~, - kend=\E[4~, - kf1=\EOP, - kf2=\EOQ, - kf3=\EOR, - kf4=\EOS, - kf5=\E[15~, - kf6=\E[17~, - kf7=\E[18~, - kf8=\E[19~, - kf9=\E[20~, - kf10=\E[21~, - kf11=\E[23~, - kf12=\E[24~, - kf13=\E[1;2P, - kf14=\E[1;2Q, - kf15=\E[1;2R, - kf16=\E[1;2S, - kf17=\E[15;2~, - kf18=\E[17;2~, - kf19=\E[18;2~, - kf20=\E[19;2~, - kf21=\E[20;2~, - kf22=\E[21;2~, - kf23=\E[23;2~, - kf24=\E[24;2~, - kf25=\E[1;5P, - kf26=\E[1;5Q, - kf27=\E[1;5R, - kf28=\E[1;5S, - kf29=\E[15;5~, - kf30=\E[17;5~, - kf31=\E[18;5~, - kf32=\E[19;5~, - kf33=\E[20;5~, - kf34=\E[21;5~, - kf35=\E[23;5~, - kf36=\E[24;5~, - kf37=\E[1;6P, - kf38=\E[1;6Q, - kf39=\E[1;6R, - kf40=\E[1;6S, - kf41=\E[15;6~, - kf42=\E[17;6~, - kf43=\E[18;6~, - kf44=\E[19;6~, - kf45=\E[20;6~, - kf46=\E[21;6~, - kf47=\E[23;6~, - kf48=\E[24;6~, - kf49=\E[1;3P, - kf50=\E[1;3Q, - kf51=\E[1;3R, - kf52=\E[1;3S, - kf53=\E[15;3~, - kf54=\E[17;3~, - kf55=\E[18;3~, - kf56=\E[19;3~, - kf57=\E[20;3~, - kf58=\E[21;3~, - kf59=\E[23;3~, - kf60=\E[24;3~, - kf61=\E[1;4P, - kf62=\E[1;4Q, - kf63=\E[1;4R, - khome=\E[1~, - kil1=\E[2;5~, - krmir=\E[2;2~, - knp=\E[6~, - kmous=\E[M, - kpp=\E[5~, - lines#24, - mir, - msgr, - npc, - op=\E[39;49m, - pairs#64, - mc0=\E[i, - mc4=\E[4i, - mc5=\E[5i, - rc=\E8, - rev=\E[7m, - ri=\EM, - rin=\E[%p1%dT, - ritm=\E[23m, - rmacs=\E(B, - rmcup=\E[?1049l, - rmir=\E[4l, - rmkx=\E[?1l\E>, - rmso=\E[27m, - rmul=\E[24m, - rs1=\Ec, - rs2=\E[4l\E>\E[?1034l, - sc=\E7, - sitm=\E[3m, - sgr0=\E[0m, - smacs=\E(0, - smcup=\E[?1049h, - smir=\E[4h, - smkx=\E[?1h\E=, - smso=\E[7m, - smul=\E[4m, - tbc=\E[3g, - tsl=\E]0;, - xenl, - vpa=\E[%i%p1%dd, -# XTerm extensions - rmxx=\E[29m, - smxx=\E[9m, - BE=\E[?2004h, - BD=\E[?2004l, - PS=\E[200~, - PE=\E[201~, -# disabled rep for now: causes some issues with older ncurses versions. -# rep=%p1%c\E[%p2%{1}%-%db, -# tmux extensions, see TERMINFO EXTENSIONS in tmux(1) - Tc, - Ms=\E]52;%p1%s;%p2%s\007, - Se=\E[2 q, - Ss=\E[%p1%d q, - -st| simpleterm, - use=st-mono, - colors#8, - setab=\E[4%p1%dm, - setaf=\E[3%p1%dm, - setb=\E[4%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m, - setf=\E[3%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m, - sgr=%?%p9%t\E(0%e\E(B%;\E[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m, - -st-256color| simpleterm with 256 colors, - use=st, - ccc, - colors#256, - oc=\E]104\007, - pairs#32767, -# Nicked from xterm-256color - initc=\E]4;%p1%d;rgb\:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\E\\, - setab=\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m, - setaf=\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m, - -st-meta| simpleterm with meta key, - use=st, - km, - rmm=\E[?1034l, - smm=\E[?1034h, - rs2=\E[4l\E>\E[?1034h, - is2=\E[4l\E>\E[?1034h, - -st-meta-256color| simpleterm with meta key and 256 colors, - use=st-256color, - km, - rmm=\E[?1034l, - smm=\E[?1034h, - rs2=\E[4l\E>\E[?1034h, - is2=\E[4l\E>\E[?1034h, - -st-bs| simpleterm with backspace as backspace, - use=st, - kbs=\010, - kdch1=\177, - -st-bs-256color| simpleterm with backspace as backspace and 256colors, - use=st-256color, - kbs=\010, - kdch1=\177, diff --git a/st/st-0.9.3/win.h b/st/st-0.9.3/win.h deleted file mode 100644 index 4d25380..0000000 --- a/st/st-0.9.3/win.h +++ /dev/null @@ -1,44 +0,0 @@ -/* See LICENSE for license details. */ - -enum win_mode { - MODE_VISIBLE = 1 << 0, - MODE_FOCUSED = 1 << 1, - MODE_APPKEYPAD = 1 << 2, - MODE_MOUSEBTN = 1 << 3, - MODE_MOUSEMOTION = 1 << 4, - MODE_REVERSE = 1 << 5, - MODE_KBDLOCK = 1 << 6, - MODE_HIDE = 1 << 7, - MODE_APPCURSOR = 1 << 8, - MODE_MOUSESGR = 1 << 9, - MODE_8BIT = 1 << 10, - MODE_BLINK = 1 << 11, - MODE_FBLINK = 1 << 12, - MODE_FOCUS = 1 << 13, - MODE_MOUSEX10 = 1 << 14, - MODE_MOUSEMANY = 1 << 15, - MODE_BRCKTPASTE = 1 << 16, - MODE_NUMLOCK = 1 << 17, - MODE_MOUSE = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10\ - |MODE_MOUSEMANY, - MODE_KBDSELECT = 1 << 18, -}; - -void xbell(void); -void xclipcopy(void); -void xdrawcursor(int, int, Glyph, int, int, Glyph); -void xdrawline(Line, int, int, int); -void xfinishdraw(void); -void xloadcols(void); -int xsetcolorname(int, const char *); -int xgetcolor(int, unsigned char *, unsigned char *, unsigned char *); -void xseticontitle(char *); -void xsettitle(char *); -int xsetcursor(int); -void xsetmode(int, unsigned int); -void xsetpointermotion(int); -void xsetsel(char *); -int xstartdraw(void); -void toggle_winmode(int); -void keyboard_select(const Arg *); -void xximspot(int, int); diff --git a/st/st-0.9.3/x.c b/st/st-0.9.3/x.c deleted file mode 100644 index ee85e4a..0000000 --- a/st/st-0.9.3/x.c +++ /dev/null @@ -1,2532 +0,0 @@ -/* See LICENSE for license details. */ -#include <errno.h> -#include <math.h> -#include <limits.h> -#include <locale.h> -#include <signal.h> -#include <sys/select.h> -#include <time.h> -#include <unistd.h> -#include <libgen.h> -#include <X11/Xatom.h> -#include <X11/Xlib.h> -#include <X11/cursorfont.h> -#include <X11/keysym.h> -#include <X11/Xft/Xft.h> -#include <X11/XKBlib.h> - -char *argv0; -#include "arg.h" -#include "st.h" -#include "win.h" - -/* types used in config.h */ -typedef struct { - uint mod; - KeySym keysym; - void (*func)(const Arg *); - const Arg arg; -} Shortcut; - -typedef struct { - uint mod; - uint button; - void (*func)(const Arg *); - const Arg arg; - uint release; - int altscrn; /* 0: don't care, -1: not alt screen, 1: alt screen */ -} MouseShortcut; - -typedef struct { - KeySym k; - uint mask; - char *s; - /* three-valued logic variables: 0 indifferent, 1 on, -1 off */ - signed char appkey; /* application keypad */ - signed char appcursor; /* application cursor */ -} Key; - -/* Undercurl slope types */ -enum undercurl_slope_type { - UNDERCURL_SLOPE_ASCENDING = 0, - UNDERCURL_SLOPE_TOP_CAP = 1, - UNDERCURL_SLOPE_DESCENDING = 2, - UNDERCURL_SLOPE_BOTTOM_CAP = 3 -}; - -/* X modifiers */ -#define XK_ANY_MOD UINT_MAX -#define XK_NO_MOD 0 -#define XK_SWITCH_MOD (1<<13|1<<14) - -/* function definitions used in config.h */ -static void clipcopy(const Arg *); -static void clippaste(const Arg *); -static void numlock(const Arg *); -static void selpaste(const Arg *); -static void zoom(const Arg *); -static void zoomabs(const Arg *); -static void zoomreset(const Arg *); -static void ttysend(const Arg *); - -/* config.h for applying patches and the configuration. */ -#include "config.h" - -/* XEMBED messages */ -#define XEMBED_FOCUS_IN 4 -#define XEMBED_FOCUS_OUT 5 - -/* macros */ -#define IS_SET(flag) ((win.mode & (flag)) != 0) -#define TRUERED(x) (((x) & 0xff0000) >> 8) -#define TRUEGREEN(x) (((x) & 0xff00)) -#define TRUEBLUE(x) (((x) & 0xff) << 8) - -typedef XftDraw *Draw; -typedef XftColor Color; -typedef XftGlyphFontSpec GlyphFontSpec; - -/* Purely graphic info */ -typedef struct { - int tw, th; /* tty width and height */ - int w, h; /* window width and height */ - int hborderpx, vborderpx; - int ch; /* char height */ - int cw; /* char width */ - int mode; /* window state/mode flags */ - int cursor; /* cursor style */ -} TermWindow; - -typedef struct { - Display *dpy; - Colormap cmap; - Window win; - Drawable buf; - GlyphFontSpec *specbuf; /* font spec buffer used for rendering */ - Atom xembed, wmdeletewin, netwmname, netwmiconname, netwmpid; - struct { - XIM xim; - XIC xic; - XPoint spot; - XVaNestedList spotlist; - } ime; - Draw draw; - Visual *vis; - XSetWindowAttributes attrs; - int scr; - int isfixed; /* is fixed geometry? */ - int l, t; /* left and top offset */ - int gm; /* geometry mask */ -} XWindow; - -typedef struct { - Atom xtarget; - char *primary, *clipboard; - struct timespec tclick1; - struct timespec tclick2; -} XSelection; - -/* Font structure */ -#define Font Font_ -typedef struct { - int height; - int width; - int ascent; - int descent; - int badslant; - int badweight; - short lbearing; - short rbearing; - XftFont *match; - FcFontSet *set; - FcPattern *pattern; -} Font; - -/* Drawing Context */ -typedef struct { - Color *col; - size_t collen; - Font font, bfont, ifont, ibfont; - GC gc; -} DC; - -static inline ushort sixd_to_16bit(int); -static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int); -static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int); -static void xdrawglyph(Glyph, int, int); -static void xclear(int, int, int, int); -static int xgeommasktogravity(int); -static int ximopen(Display *); -static void ximinstantiate(Display *, XPointer, XPointer); -static void ximdestroy(XIM, XPointer, XPointer); -static int xicdestroy(XIC, XPointer, XPointer); -static void xinit(int, int); -static void cresize(int, int); -static void xresize(int, int); -static void xhints(void); -static int xloadcolor(int, const char *, Color *); -static int xloadfont(Font *, FcPattern *); -static void xloadfonts(const char *, double); -static void xunloadfont(Font *); -static void xunloadfonts(void); -static void xsetenv(void); -static void xseturgency(int); -static int evcol(XEvent *); -static int evrow(XEvent *); - -static void expose(XEvent *); -static void visibility(XEvent *); -static void unmap(XEvent *); -static void kpress(XEvent *); -static void cmessage(XEvent *); -static void resize(XEvent *); -static void focus(XEvent *); -static uint buttonmask(uint); -static int mouseaction(XEvent *, uint); -static void brelease(XEvent *); -static void bpress(XEvent *); -static void bmotion(XEvent *); -static void propnotify(XEvent *); -static void selnotify(XEvent *); -static void selclear_(XEvent *); -static void selrequest(XEvent *); -static void setsel(char *, Time); -static void mousesel(XEvent *, int); -static void mousereport(XEvent *); -static char *kmap(KeySym, uint); -static int match(uint, uint); - -static void run(void); -static void usage(void); - -static void (*handler[LASTEvent])(XEvent *) = { - [KeyPress] = kpress, - [ClientMessage] = cmessage, - [ConfigureNotify] = resize, - [VisibilityNotify] = visibility, - [UnmapNotify] = unmap, - [Expose] = expose, - [FocusIn] = focus, - [FocusOut] = focus, - [MotionNotify] = bmotion, - [ButtonPress] = bpress, - [ButtonRelease] = brelease, -/* - * Uncomment if you want the selection to disappear when you select something - * different in another window. - */ -/* [SelectionClear] = selclear_, */ - [SelectionNotify] = selnotify, -/* - * PropertyNotify is only turned on when there is some INCR transfer happening - * for the selection retrieval. - */ - [PropertyNotify] = propnotify, - [SelectionRequest] = selrequest, -}; - -/* Globals */ -static DC dc; -static XWindow xw; -static XSelection xsel; -static TermWindow win; - -/* Font Ring Cache */ -enum { - FRC_NORMAL, - FRC_ITALIC, - FRC_BOLD, - FRC_ITALICBOLD -}; - -typedef struct { - XftFont *font; - int flags; - Rune unicodep; -} Fontcache; - -/* Fontcache is an array now. A new font will be appended to the array. */ -static Fontcache *frc = NULL; -static int frclen = 0; -static int frccap = 0; -static char *usedfont = NULL; -static double usedfontsize = 0; -static double defaultfontsize = 0; - -static char *opt_class = NULL; -static char **opt_cmd = NULL; -static char *opt_embed = NULL; -static char *opt_font = NULL; -static char *opt_io = NULL; -static char *opt_line = NULL; -static char *opt_name = NULL; -static char *opt_title = NULL; - -static uint buttons; /* bit field of pressed buttons */ - -void -clipcopy(const Arg *dummy) -{ - Atom clipboard; - - free(xsel.clipboard); - xsel.clipboard = NULL; - - if (xsel.primary != NULL) { - xsel.clipboard = xstrdup(xsel.primary); - clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - XSetSelectionOwner(xw.dpy, clipboard, xw.win, CurrentTime); - } -} - -void -clippaste(const Arg *dummy) -{ - Atom clipboard; - - clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - XConvertSelection(xw.dpy, clipboard, xsel.xtarget, clipboard, - xw.win, CurrentTime); -} - -void -selpaste(const Arg *dummy) -{ - XConvertSelection(xw.dpy, XA_PRIMARY, xsel.xtarget, XA_PRIMARY, - xw.win, CurrentTime); -} - -void -numlock(const Arg *dummy) -{ - win.mode ^= MODE_NUMLOCK; -} - -void -zoom(const Arg *arg) -{ - Arg larg; - - larg.f = usedfontsize + arg->f; - zoomabs(&larg); -} - -void -zoomabs(const Arg *arg) -{ - xunloadfonts(); - xloadfonts(usedfont, arg->f); - cresize(0, 0); - redraw(); - xhints(); -} - -void -zoomreset(const Arg *arg) -{ - Arg larg; - - if (defaultfontsize > 0) { - larg.f = defaultfontsize; - zoomabs(&larg); - } -} - -void -ttysend(const Arg *arg) -{ - ttywrite(arg->s, strlen(arg->s), 1); -} - -int -evcol(XEvent *e) -{ - int x = e->xbutton.x - win.hborderpx; - LIMIT(x, 0, win.tw - 1); - return x / win.cw; -} - -int -evrow(XEvent *e) -{ - int y = e->xbutton.y - win.vborderpx; - LIMIT(y, 0, win.th - 1); - return y / win.ch; -} - -void -mousesel(XEvent *e, int done) -{ - int type, seltype = SEL_REGULAR; - uint state = e->xbutton.state & ~(Button1Mask | forcemousemod); - - for (type = 1; type < LEN(selmasks); ++type) { - if (match(selmasks[type], state)) { - seltype = type; - break; - } - } - selextend(evcol(e), evrow(e), seltype, done); - if (done) - setsel(getsel(), e->xbutton.time); -} - -void -mousereport(XEvent *e) -{ - int len, btn, code; - int x = evcol(e), y = evrow(e); - int state = e->xbutton.state; - char buf[40]; - static int ox, oy; - - if (e->type == MotionNotify) { - if (x == ox && y == oy) - return; - if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY)) - return; - /* MODE_MOUSEMOTION: no reporting if no button is pressed */ - if (IS_SET(MODE_MOUSEMOTION) && buttons == 0) - return; - /* Set btn to lowest-numbered pressed button, or 12 if no - * buttons are pressed. */ - for (btn = 1; btn <= 11 && !(buttons & (1<<(btn-1))); btn++) - ; - code = 32; - } else { - btn = e->xbutton.button; - /* Only buttons 1 through 11 can be encoded */ - if (btn < 1 || btn > 11) - return; - if (e->type == ButtonRelease) { - /* MODE_MOUSEX10: no button release reporting */ - if (IS_SET(MODE_MOUSEX10)) - return; - /* Don't send release events for the scroll wheel */ - if (btn == 4 || btn == 5) - return; - } - code = 0; - } - - ox = x; - oy = y; - - /* Encode btn into code. If no button is pressed for a motion event in - * MODE_MOUSEMANY, then encode it as a release. */ - if ((!IS_SET(MODE_MOUSESGR) && e->type == ButtonRelease) || btn == 12) - code += 3; - else if (btn >= 8) - code += 128 + btn - 8; - else if (btn >= 4) - code += 64 + btn - 4; - else - code += btn - 1; - - if (!IS_SET(MODE_MOUSEX10)) { - code += ((state & ShiftMask ) ? 4 : 0) - + ((state & Mod1Mask ) ? 8 : 0) /* meta key: alt */ - + ((state & ControlMask) ? 16 : 0); - } - - if (IS_SET(MODE_MOUSESGR)) { - len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", - code, x+1, y+1, - e->type == ButtonRelease ? 'm' : 'M'); - } else if (x < 223 && y < 223) { - len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", - 32+code, 32+x+1, 32+y+1); - } else { - return; - } - - ttywrite(buf, len, 0); -} - -uint -buttonmask(uint button) -{ - return button == Button1 ? Button1Mask - : button == Button2 ? Button2Mask - : button == Button3 ? Button3Mask - : button == Button4 ? Button4Mask - : button == Button5 ? Button5Mask - : 0; -} - -int -mouseaction(XEvent *e, uint release) -{ - MouseShortcut *ms; - - /* ignore Button<N>mask for Button<N> - it's set on release */ - uint state = e->xbutton.state & ~buttonmask(e->xbutton.button); - - for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { - if (ms->release == release && - ms->button == e->xbutton.button && - (!ms->altscrn || (ms->altscrn == (tisaltscr() ? 1 : -1))) && - (match(ms->mod, state) || /* exact or forced */ - match(ms->mod, state & ~forcemousemod))) { - ms->func(&(ms->arg)); - return 1; - } - } - - return 0; -} - -void -bpress(XEvent *e) -{ - int btn = e->xbutton.button; - struct timespec now; - int snap; - - if (1 <= btn && btn <= 11) - buttons |= 1 << (btn-1); - - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { - mousereport(e); - return; - } - - if (mouseaction(e, 0)) - return; - - if (btn == Button1) { - /* - * If the user clicks below predefined timeouts specific - * snapping behaviour is exposed. - */ - clock_gettime(CLOCK_MONOTONIC, &now); - if (TIMEDIFF(now, xsel.tclick2) <= tripleclicktimeout) { - snap = SNAP_LINE; - } else if (TIMEDIFF(now, xsel.tclick1) <= doubleclicktimeout) { - snap = SNAP_WORD; - } else { - snap = 0; - } - xsel.tclick2 = xsel.tclick1; - xsel.tclick1 = now; - - selstart(evcol(e), evrow(e), snap); - } -} - -void -propnotify(XEvent *e) -{ - XPropertyEvent *xpev; - Atom clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - - xpev = &e->xproperty; - if (xpev->state == PropertyNewValue && - (xpev->atom == XA_PRIMARY || - xpev->atom == clipboard)) { - selnotify(e); - } -} - -void -selnotify(XEvent *e) -{ - ulong nitems, ofs, rem; - int format; - uchar *data, *last, *repl; - Atom type, incratom, property = None; - - incratom = XInternAtom(xw.dpy, "INCR", 0); - - ofs = 0; - if (e->type == SelectionNotify) - property = e->xselection.property; - else if (e->type == PropertyNotify) - property = e->xproperty.atom; - - if (property == None) - return; - - do { - if (XGetWindowProperty(xw.dpy, xw.win, property, ofs, - BUFSIZ/4, False, AnyPropertyType, - &type, &format, &nitems, &rem, - &data)) { - fprintf(stderr, "Clipboard allocation failed\n"); - return; - } - - if (e->type == PropertyNotify && nitems == 0 && rem == 0) { - /* - * If there is some PropertyNotify with no data, then - * this is the signal of the selection owner that all - * data has been transferred. We won't need to receive - * PropertyNotify events anymore. - */ - MODBIT(xw.attrs.event_mask, 0, PropertyChangeMask); - XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, - &xw.attrs); - } - - if (type == incratom) { - /* - * Activate the PropertyNotify events so we receive - * when the selection owner does send us the next - * chunk of data. - */ - MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask); - XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, - &xw.attrs); - - /* - * Deleting the property is the transfer start signal. - */ - XDeleteProperty(xw.dpy, xw.win, (int)property); - continue; - } - - /* - * As seen in getsel: - * Line endings are inconsistent in the terminal and GUI world - * copy and pasting. When receiving some selection data, - * replace all '\n' with '\r'. - * FIXME: Fix the computer world. - */ - repl = data; - last = data + nitems * format / 8; - while ((repl = memchr(repl, '\n', last - repl))) { - *repl++ = '\r'; - } - - if (IS_SET(MODE_BRCKTPASTE) && ofs == 0) - ttywrite("\033[200~", 6, 0); - ttywrite((char *)data, nitems * format / 8, 1); - if (IS_SET(MODE_BRCKTPASTE) && rem == 0) - ttywrite("\033[201~", 6, 0); - XFree(data); - /* number of 32-bit chunks returned */ - ofs += nitems * format / 32; - } while (rem > 0); - - /* - * Deleting the property again tells the selection owner to send the - * next data chunk in the property. - */ - XDeleteProperty(xw.dpy, xw.win, (int)property); -} - -void -xclipcopy(void) -{ - clipcopy(NULL); -} - -void -selclear_(XEvent *e) -{ - selclear(); -} - -void -selrequest(XEvent *e) -{ - XSelectionRequestEvent *xsre; - XSelectionEvent xev; - Atom xa_targets, string, clipboard; - char *seltext; - - xsre = (XSelectionRequestEvent *) e; - xev.type = SelectionNotify; - xev.requestor = xsre->requestor; - xev.selection = xsre->selection; - xev.target = xsre->target; - xev.time = xsre->time; - if (xsre->property == None) - xsre->property = xsre->target; - - /* reject */ - xev.property = None; - - xa_targets = XInternAtom(xw.dpy, "TARGETS", 0); - if (xsre->target == xa_targets) { - /* respond with the supported type */ - string = xsel.xtarget; - XChangeProperty(xsre->display, xsre->requestor, xsre->property, - XA_ATOM, 32, PropModeReplace, - (uchar *) &string, 1); - xev.property = xsre->property; - } else if (xsre->target == xsel.xtarget || xsre->target == XA_STRING) { - /* - * xith XA_STRING non ascii characters may be incorrect in the - * requestor. It is not our problem, use utf8. - */ - clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0); - if (xsre->selection == XA_PRIMARY) { - seltext = xsel.primary; - } else if (xsre->selection == clipboard) { - seltext = xsel.clipboard; - } else { - fprintf(stderr, - "Unhandled clipboard selection 0x%lx\n", - xsre->selection); - return; - } - if (seltext != NULL) { - XChangeProperty(xsre->display, xsre->requestor, - xsre->property, xsre->target, - 8, PropModeReplace, - (uchar *)seltext, strlen(seltext)); - xev.property = xsre->property; - } - } - - /* all done, send a notification to the listener */ - if (!XSendEvent(xsre->display, xsre->requestor, 1, 0, (XEvent *) &xev)) - fprintf(stderr, "Error sending SelectionNotify event\n"); -} - -void -setsel(char *str, Time t) -{ - if (!str) - return; - - free(xsel.primary); - xsel.primary = str; - - XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t); - if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win) - selclear(); -} - -void -xsetsel(char *str) -{ - setsel(str, CurrentTime); -} - -void -brelease(XEvent *e) -{ - int btn = e->xbutton.button; - - if (1 <= btn && btn <= 11) - buttons &= ~(1 << (btn-1)); - - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { - mousereport(e); - return; - } - - if (mouseaction(e, 1)) - return; - if (btn == Button1) - mousesel(e, 1); -} - -void -bmotion(XEvent *e) -{ - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { - mousereport(e); - return; - } - - mousesel(e, 0); -} - -void -cresize(int width, int height) -{ - int col, row; - - if (width != 0) - win.w = width; - if (height != 0) - win.h = height; - - col = (win.w - 2 * borderpx) / win.cw; - row = (win.h - 2 * borderpx) / win.ch; - col = MAX(1, col); - row = MAX(1, row); - - win.hborderpx = (win.w - col * win.cw) / 2; - win.vborderpx = (win.h - row * win.ch) / 2; - - tresize(col, row); - xresize(col, row); - ttyresize(win.tw, win.th); -} - -void -xresize(int col, int row) -{ - win.tw = col * win.cw; - win.th = row * win.ch; - - XFreePixmap(xw.dpy, xw.buf); - xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, - DefaultDepth(xw.dpy, xw.scr)); - XftDrawChange(xw.draw, xw.buf); - xclear(0, 0, win.w, win.h); - - /* resize to new width */ - xw.specbuf = xrealloc(xw.specbuf, col * sizeof(GlyphFontSpec)); -} - -ushort -sixd_to_16bit(int x) -{ - return x == 0 ? 0 : 0x3737 + 0x2828 * x; -} - -int -xloadcolor(int i, const char *name, Color *ncolor) -{ - XRenderColor color = { .alpha = 0xffff }; - - if (!name) { - if (BETWEEN(i, 16, 255)) { /* 256 color */ - if (i < 6*6*6+16) { /* same colors as xterm */ - color.red = sixd_to_16bit( ((i-16)/36)%6 ); - color.green = sixd_to_16bit( ((i-16)/6) %6 ); - color.blue = sixd_to_16bit( ((i-16)/1) %6 ); - } else { /* greyscale */ - color.red = 0x0808 + 0x0a0a * (i - (6*6*6+16)); - color.green = color.blue = color.red; - } - return XftColorAllocValue(xw.dpy, xw.vis, - xw.cmap, &color, ncolor); - } else - name = colorname[i]; - } - - return XftColorAllocName(xw.dpy, xw.vis, xw.cmap, name, ncolor); -} - -void -xloadcols(void) -{ - int i; - static int loaded; - Color *cp; - - if (loaded) { - for (cp = dc.col; cp < &dc.col[dc.collen]; ++cp) - XftColorFree(xw.dpy, xw.vis, xw.cmap, cp); - } else { - dc.collen = MAX(LEN(colorname), 256); - dc.col = xmalloc(dc.collen * sizeof(Color)); - } - - for (i = 0; i < dc.collen; i++) - if (!xloadcolor(i, NULL, &dc.col[i])) { - if (colorname[i]) - die("could not allocate color '%s'\n", colorname[i]); - else - die("could not allocate color %d\n", i); - } - loaded = 1; -} - -int -xgetcolor(int x, unsigned char *r, unsigned char *g, unsigned char *b) -{ - if (!BETWEEN(x, 0, dc.collen - 1)) - return 1; - - *r = dc.col[x].color.red >> 8; - *g = dc.col[x].color.green >> 8; - *b = dc.col[x].color.blue >> 8; - - return 0; -} - -int -xsetcolorname(int x, const char *name) -{ - Color ncolor; - - if (!BETWEEN(x, 0, dc.collen - 1)) - return 1; - - if (!xloadcolor(x, name, &ncolor)) - return 1; - - XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]); - dc.col[x] = ncolor; - - return 0; -} - -/* - * Absolute coordinates. - */ -void -xclear(int x1, int y1, int x2, int y2) -{ - XftDrawRect(xw.draw, - &dc.col[IS_SET(MODE_REVERSE)? defaultfg : defaultbg], - x1, y1, x2-x1, y2-y1); -} - -void -xhints(void) -{ - XClassHint class = {opt_name ? opt_name : termname, - opt_class ? opt_class : termname}; - XWMHints wm = {.flags = InputHint, .input = 1}; - XSizeHints *sizeh; - - sizeh = XAllocSizeHints(); - - sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize; - sizeh->height = win.h; - sizeh->width = win.w; - sizeh->height_inc = 1; - sizeh->width_inc = 1; - sizeh->base_height = 2 * borderpx; - sizeh->base_width = 2 * borderpx; - sizeh->min_height = win.ch + 2 * borderpx; - sizeh->min_width = win.cw + 2 * borderpx; - if (xw.isfixed) { - sizeh->flags |= PMaxSize; - sizeh->min_width = sizeh->max_width = win.w; - sizeh->min_height = sizeh->max_height = win.h; - } - if (xw.gm & (XValue|YValue)) { - sizeh->flags |= USPosition | PWinGravity; - sizeh->x = xw.l; - sizeh->y = xw.t; - sizeh->win_gravity = xgeommasktogravity(xw.gm); - } - - XSetWMProperties(xw.dpy, xw.win, NULL, NULL, NULL, 0, sizeh, &wm, - &class); - XFree(sizeh); -} - -int -xgeommasktogravity(int mask) -{ - switch (mask & (XNegative|YNegative)) { - case 0: - return NorthWestGravity; - case XNegative: - return NorthEastGravity; - case YNegative: - return SouthWestGravity; - } - - return SouthEastGravity; -} - -int -xloadfont(Font *f, FcPattern *pattern) -{ - FcPattern *configured; - FcPattern *match; - FcResult result; - XGlyphInfo extents; - int wantattr, haveattr; - - /* - * Manually configure instead of calling XftMatchFont - * so that we can use the configured pattern for - * "missing glyph" lookups. - */ - configured = FcPatternDuplicate(pattern); - if (!configured) - return 1; - - FcConfigSubstitute(NULL, configured, FcMatchPattern); - XftDefaultSubstitute(xw.dpy, xw.scr, configured); - - match = FcFontMatch(NULL, configured, &result); - if (!match) { - FcPatternDestroy(configured); - return 1; - } - - if (!(f->match = XftFontOpenPattern(xw.dpy, match))) { - FcPatternDestroy(configured); - FcPatternDestroy(match); - return 1; - } - - if ((XftPatternGetInteger(pattern, "slant", 0, &wantattr) == - XftResultMatch)) { - /* - * Check if xft was unable to find a font with the appropriate - * slant but gave us one anyway. Try to mitigate. - */ - if ((XftPatternGetInteger(f->match->pattern, "slant", 0, - &haveattr) != XftResultMatch) || haveattr < wantattr) { - f->badslant = 1; - fputs("font slant does not match\n", stderr); - } - } - - if ((XftPatternGetInteger(pattern, "weight", 0, &wantattr) == - XftResultMatch)) { - if ((XftPatternGetInteger(f->match->pattern, "weight", 0, - &haveattr) != XftResultMatch) || haveattr != wantattr) { - f->badweight = 1; - fputs("font weight does not match\n", stderr); - } - } - - XftTextExtentsUtf8(xw.dpy, f->match, - (const FcChar8 *) ascii_printable, - strlen(ascii_printable), &extents); - - f->set = NULL; - f->pattern = configured; - - f->ascent = f->match->ascent; - f->descent = f->match->descent; - f->lbearing = 0; - f->rbearing = f->match->max_advance_width; - - f->height = f->ascent + f->descent; - f->width = DIVCEIL(extents.xOff, strlen(ascii_printable)); - - return 0; -} - -void -xloadfonts(const char *fontstr, double fontsize) -{ - FcPattern *pattern; - double fontval; - - if (fontstr[0] == '-') - pattern = XftXlfdParse(fontstr, False, False); - else - pattern = FcNameParse((const FcChar8 *)fontstr); - - if (!pattern) - die("can't open font %s\n", fontstr); - - if (fontsize > 1) { - FcPatternDel(pattern, FC_PIXEL_SIZE); - FcPatternDel(pattern, FC_SIZE); - FcPatternAddDouble(pattern, FC_PIXEL_SIZE, (double)fontsize); - usedfontsize = fontsize; - } else { - if (FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) == - FcResultMatch) { - usedfontsize = fontval; - } else if (FcPatternGetDouble(pattern, FC_SIZE, 0, &fontval) == - FcResultMatch) { - usedfontsize = -1; - } else { - /* - * Default font size is 12, if none given. This is to - * have a known usedfontsize value. - */ - FcPatternAddDouble(pattern, FC_PIXEL_SIZE, 12); - usedfontsize = 12; - } - defaultfontsize = usedfontsize; - } - - if (xloadfont(&dc.font, pattern)) - die("can't open font %s\n", fontstr); - - if (usedfontsize < 0) { - FcPatternGetDouble(dc.font.match->pattern, - FC_PIXEL_SIZE, 0, &fontval); - usedfontsize = fontval; - if (fontsize == 0) - defaultfontsize = fontval; - } - - /* Setting character width and height. */ - win.cw = ceilf(dc.font.width * cwscale); - win.ch = ceilf(dc.font.height * chscale); - - FcPatternDel(pattern, FC_SLANT); - FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); - if (xloadfont(&dc.ifont, pattern)) - die("can't open font %s\n", fontstr); - - FcPatternDel(pattern, FC_WEIGHT); - FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); - if (xloadfont(&dc.ibfont, pattern)) - die("can't open font %s\n", fontstr); - - FcPatternDel(pattern, FC_SLANT); - FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN); - if (xloadfont(&dc.bfont, pattern)) - die("can't open font %s\n", fontstr); - - FcPatternDestroy(pattern); -} - -void -xunloadfont(Font *f) -{ - XftFontClose(xw.dpy, f->match); - FcPatternDestroy(f->pattern); - if (f->set) - FcFontSetDestroy(f->set); -} - -void -xunloadfonts(void) -{ - /* Free the loaded fonts in the font cache. */ - while (frclen > 0) - XftFontClose(xw.dpy, frc[--frclen].font); - - xunloadfont(&dc.font); - xunloadfont(&dc.bfont); - xunloadfont(&dc.ifont); - xunloadfont(&dc.ibfont); -} - -int -ximopen(Display *dpy) -{ - XIMCallback imdestroy = { .client_data = NULL, .callback = ximdestroy }; - XICCallback icdestroy = { .client_data = NULL, .callback = xicdestroy }; - - xw.ime.xim = XOpenIM(xw.dpy, NULL, NULL, NULL); - if (xw.ime.xim == NULL) - return 0; - - if (XSetIMValues(xw.ime.xim, XNDestroyCallback, &imdestroy, NULL)) - fprintf(stderr, "XSetIMValues: " - "Could not set XNDestroyCallback.\n"); - - xw.ime.spotlist = XVaCreateNestedList(0, XNSpotLocation, &xw.ime.spot, - NULL); - - if (xw.ime.xic == NULL) { - xw.ime.xic = XCreateIC(xw.ime.xim, XNInputStyle, - XIMPreeditNothing | XIMStatusNothing, - XNClientWindow, xw.win, - XNDestroyCallback, &icdestroy, - NULL); - } - if (xw.ime.xic == NULL) - fprintf(stderr, "XCreateIC: Could not create input context.\n"); - - return 1; -} - -void -ximinstantiate(Display *dpy, XPointer client, XPointer call) -{ - if (ximopen(dpy)) - XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, - ximinstantiate, NULL); -} - -void -ximdestroy(XIM xim, XPointer client, XPointer call) -{ - xw.ime.xim = NULL; - XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, - ximinstantiate, NULL); - XFree(xw.ime.spotlist); -} - -int -xicdestroy(XIC xim, XPointer client, XPointer call) -{ - xw.ime.xic = NULL; - return 1; -} - -void -xinit(int cols, int rows) -{ - XGCValues gcvalues; - Cursor cursor; - Window parent, root; - pid_t thispid = getpid(); - XColor xmousefg, xmousebg; - - if (!(xw.dpy = XOpenDisplay(NULL))) - die("can't open display\n"); - xw.scr = XDefaultScreen(xw.dpy); - xw.vis = XDefaultVisual(xw.dpy, xw.scr); - - /* font */ - if (!FcInit()) - die("could not init fontconfig.\n"); - - usedfont = (opt_font == NULL)? font : opt_font; - xloadfonts(usedfont, 0); - - /* colors */ - xw.cmap = XDefaultColormap(xw.dpy, xw.scr); - xloadcols(); - - /* adjust fixed window geometry */ - win.w = 2 * win.hborderpx + 2 * borderpx + cols * win.cw; - win.h = 2 * win.vborderpx + 2 * borderpx + rows * win.ch; - if (xw.gm & XNegative) - xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2; - if (xw.gm & YNegative) - xw.t += DisplayHeight(xw.dpy, xw.scr) - win.h - 2; - - /* Events */ - xw.attrs.background_pixel = dc.col[defaultbg].pixel; - xw.attrs.border_pixel = dc.col[defaultbg].pixel; - xw.attrs.bit_gravity = NorthWestGravity; - xw.attrs.event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask - | ExposureMask | VisibilityChangeMask | StructureNotifyMask - | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask; - xw.attrs.colormap = xw.cmap; - - root = XRootWindow(xw.dpy, xw.scr); - if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) - parent = root; - xw.win = XCreateWindow(xw.dpy, root, xw.l, xw.t, - win.w, win.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput, - xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity - | CWEventMask | CWColormap, &xw.attrs); - if (parent != root) - XReparentWindow(xw.dpy, xw.win, parent, xw.l, xw.t); - - memset(&gcvalues, 0, sizeof(gcvalues)); - gcvalues.graphics_exposures = False; - dc.gc = XCreateGC(xw.dpy, xw.win, GCGraphicsExposures, - &gcvalues); - xw.buf = XCreatePixmap(xw.dpy, xw.win, win.w, win.h, - DefaultDepth(xw.dpy, xw.scr)); - XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel); - XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, win.w, win.h); - - /* font spec buffer */ - xw.specbuf = xmalloc(cols * sizeof(GlyphFontSpec)); - - /* Xft rendering context */ - xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); - - /* input methods */ - if (!ximopen(xw.dpy)) { - XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, - ximinstantiate, NULL); - } - - /* white cursor, black outline */ - cursor = XCreateFontCursor(xw.dpy, mouseshape); - XDefineCursor(xw.dpy, xw.win, cursor); - - if (XParseColor(xw.dpy, xw.cmap, colorname[mousefg], &xmousefg) == 0) { - xmousefg.red = 0xffff; - xmousefg.green = 0xffff; - xmousefg.blue = 0xffff; - } - - if (XParseColor(xw.dpy, xw.cmap, colorname[mousebg], &xmousebg) == 0) { - xmousebg.red = 0x0000; - xmousebg.green = 0x0000; - xmousebg.blue = 0x0000; - } - - XRecolorCursor(xw.dpy, cursor, &xmousefg, &xmousebg); - - xw.xembed = XInternAtom(xw.dpy, "_XEMBED", False); - xw.wmdeletewin = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False); - xw.netwmname = XInternAtom(xw.dpy, "_NET_WM_NAME", False); - xw.netwmiconname = XInternAtom(xw.dpy, "_NET_WM_ICON_NAME", False); - XSetWMProtocols(xw.dpy, xw.win, &xw.wmdeletewin, 1); - - xw.netwmpid = XInternAtom(xw.dpy, "_NET_WM_PID", False); - XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32, - PropModeReplace, (uchar *)&thispid, 1); - - win.mode = MODE_NUMLOCK; - resettitle(); - xhints(); - XMapWindow(xw.dpy, xw.win); - XSync(xw.dpy, False); - - clock_gettime(CLOCK_MONOTONIC, &xsel.tclick1); - clock_gettime(CLOCK_MONOTONIC, &xsel.tclick2); - xsel.primary = NULL; - xsel.clipboard = NULL; - xsel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0); - if (xsel.xtarget == None) - xsel.xtarget = XA_STRING; -} - -int -xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y) -{ - float winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch, xp, yp; - ushort mode, prevmode = USHRT_MAX; - Font *font = &dc.font; - int frcflags = FRC_NORMAL; - float runewidth = win.cw; - Rune rune; - FT_UInt glyphidx; - FcResult fcres; - FcPattern *fcpattern, *fontpattern; - FcFontSet *fcsets[] = { NULL }; - FcCharSet *fccharset; - int i, f, numspecs = 0; - - for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) { - /* Fetch rune and mode for current glyph. */ - rune = glyphs[i].u; - mode = glyphs[i].mode; - - /* Skip dummy wide-character spacing. */ - if (mode == ATTR_WDUMMY) - continue; - - /* Determine font for glyph if different from previous glyph. */ - if (prevmode != mode) { - prevmode = mode; - font = &dc.font; - frcflags = FRC_NORMAL; - runewidth = win.cw * ((mode & ATTR_WIDE) ? 2.0f : 1.0f); - if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD)) { - font = &dc.ibfont; - frcflags = FRC_ITALICBOLD; - } else if (mode & ATTR_ITALIC) { - font = &dc.ifont; - frcflags = FRC_ITALIC; - } else if (mode & ATTR_BOLD) { - font = &dc.bfont; - frcflags = FRC_BOLD; - } - yp = winy + font->ascent; - } - - /* Lookup character index with default font. */ - glyphidx = XftCharIndex(xw.dpy, font->match, rune); - if (glyphidx) { - specs[numspecs].font = font->match; - specs[numspecs].glyph = glyphidx; - specs[numspecs].x = (short)xp; - specs[numspecs].y = (short)yp; - xp += runewidth; - numspecs++; - continue; - } - - /* Fallback on font cache, search the font cache for match. */ - for (f = 0; f < frclen; f++) { - glyphidx = XftCharIndex(xw.dpy, frc[f].font, rune); - /* Everything correct. */ - if (glyphidx && frc[f].flags == frcflags) - break; - /* We got a default font for a not found glyph. */ - if (!glyphidx && frc[f].flags == frcflags - && frc[f].unicodep == rune) { - break; - } - } - - /* Nothing was found. Use fontconfig to find matching font. */ - if (f >= frclen) { - if (!font->set) - font->set = FcFontSort(0, font->pattern, - 1, 0, &fcres); - fcsets[0] = font->set; - - /* - * Nothing was found in the cache. Now use - * some dozen of Fontconfig calls to get the - * font for one single character. - * - * Xft and fontconfig are design failures. - */ - fcpattern = FcPatternDuplicate(font->pattern); - fccharset = FcCharSetCreate(); - - FcCharSetAddChar(fccharset, rune); - FcPatternAddCharSet(fcpattern, FC_CHARSET, - fccharset); - FcPatternAddBool(fcpattern, FC_SCALABLE, 1); - - FcConfigSubstitute(0, fcpattern, - FcMatchPattern); - FcDefaultSubstitute(fcpattern); - - fontpattern = FcFontSetMatch(0, fcsets, 1, - fcpattern, &fcres); - - /* Allocate memory for the new cache entry. */ - if (frclen >= frccap) { - frccap += 16; - frc = xrealloc(frc, frccap * sizeof(Fontcache)); - } - - frc[frclen].font = XftFontOpenPattern(xw.dpy, - fontpattern); - if (!frc[frclen].font) - die("XftFontOpenPattern failed seeking fallback font: %s\n", - strerror(errno)); - frc[frclen].flags = frcflags; - frc[frclen].unicodep = rune; - - glyphidx = XftCharIndex(xw.dpy, frc[frclen].font, rune); - - f = frclen; - frclen++; - - FcPatternDestroy(fcpattern); - FcCharSetDestroy(fccharset); - } - - specs[numspecs].font = frc[f].font; - specs[numspecs].glyph = glyphidx; - specs[numspecs].x = (short)xp; - specs[numspecs].y = (short)yp; - xp += runewidth; - numspecs++; - } - - return numspecs; -} - -static int isSlopeRising (int x, int iPoint, int waveWidth) -{ - // . . . . - // / \ / \ / \ / \ - // / \ / \ / \ / \ - // . . . . . - - // Find absolute `x` of point - x += iPoint * (waveWidth/2); - - // Find index of absolute wave - int absSlope = x / ((float)waveWidth/2); - - return (absSlope % 2); -} - -static int getSlope (int x, int iPoint, int waveWidth) -{ - // Sizes: Caps are half width of slopes - // 1_2 1_2 1_2 1_2 - // / \ / \ / \ / \ - // / \ / \ / \ / \ - // 0 3_0 3_0 3_0 3_ - // <2-> <1> <---6----> - - // Find type of first point - int firstType; - x -= (x / waveWidth) * waveWidth; - if (x < (waveWidth * (2.f/6.f))) - firstType = UNDERCURL_SLOPE_ASCENDING; - else if (x < (waveWidth * (3.f/6.f))) - firstType = UNDERCURL_SLOPE_TOP_CAP; - else if (x < (waveWidth * (5.f/6.f))) - firstType = UNDERCURL_SLOPE_DESCENDING; - else - firstType = UNDERCURL_SLOPE_BOTTOM_CAP; - - // Find type of given point - int pointType = (iPoint % 4); - pointType += firstType; - pointType %= 4; - - return pointType; -} - -void -xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y) -{ - int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1); - int winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch, - width = charlen * win.cw; - Color *fg, *bg, *temp, revfg, revbg, truefg, truebg; - XRenderColor colfg, colbg; - XRectangle r; - - /* Fallback on color display for attributes not supported by the font */ - if (base.mode & ATTR_ITALIC && base.mode & ATTR_BOLD) { - if (dc.ibfont.badslant || dc.ibfont.badweight) - base.fg = defaultattr; - } else if ((base.mode & ATTR_ITALIC && dc.ifont.badslant) || - (base.mode & ATTR_BOLD && dc.bfont.badweight)) { - base.fg = defaultattr; - } - - if (IS_TRUECOL(base.fg)) { - colfg.alpha = 0xffff; - colfg.red = TRUERED(base.fg); - colfg.green = TRUEGREEN(base.fg); - colfg.blue = TRUEBLUE(base.fg); - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &truefg); - fg = &truefg; - } else { - fg = &dc.col[base.fg]; - } - - if (IS_TRUECOL(base.bg)) { - colbg.alpha = 0xffff; - colbg.green = TRUEGREEN(base.bg); - colbg.red = TRUERED(base.bg); - colbg.blue = TRUEBLUE(base.bg); - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &truebg); - bg = &truebg; - } else { - bg = &dc.col[base.bg]; - } - - /* Change basic system colors [0-7] to bright system colors [8-15] */ - if ((base.mode & ATTR_BOLD_FAINT) == ATTR_BOLD && BETWEEN(base.fg, 0, 7)) - fg = &dc.col[base.fg + 8]; - - if (IS_SET(MODE_REVERSE)) { - if (fg == &dc.col[defaultfg]) { - fg = &dc.col[defaultbg]; - } else { - colfg.red = ~fg->color.red; - colfg.green = ~fg->color.green; - colfg.blue = ~fg->color.blue; - colfg.alpha = fg->color.alpha; - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, - &revfg); - fg = &revfg; - } - - if (bg == &dc.col[defaultbg]) { - bg = &dc.col[defaultfg]; - } else { - colbg.red = ~bg->color.red; - colbg.green = ~bg->color.green; - colbg.blue = ~bg->color.blue; - colbg.alpha = bg->color.alpha; - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, - &revbg); - bg = &revbg; - } - } - - if ((base.mode & ATTR_BOLD_FAINT) == ATTR_FAINT) { - colfg.red = fg->color.red / 2; - colfg.green = fg->color.green / 2; - colfg.blue = fg->color.blue / 2; - colfg.alpha = fg->color.alpha; - XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &revfg); - fg = &revfg; - } - - if (base.mode & ATTR_REVERSE) { - temp = fg; - fg = bg; - bg = temp; - } - - if (base.mode & ATTR_BLINK && win.mode & MODE_BLINK) - fg = bg; - - if (base.mode & ATTR_INVISIBLE) - fg = bg; - - /* Intelligent cleaning up of the borders. */ - if (x == 0) { - xclear(0, (y == 0)? 0 : winy, win.hborderpx, - winy + win.ch + - ((winy + win.ch >= win.vborderpx + win.th)? win.h : 0)); - } - if (winx + width >= win.hborderpx + win.tw) { - xclear(winx + width, (y == 0)? 0 : winy, win.w, - ((winy + win.ch >= win.vborderpx + win.th)? win.h : (winy + win.ch))); - } - if (y == 0) - xclear(winx, 0, winx + width, win.vborderpx); - if (winy + win.ch >= win.vborderpx + win.th) - xclear(winx, winy + win.ch, winx + width, win.h); - - /* Clean up the region we want to draw to. */ - XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); - - /* Set the clip region because Xft is sometimes dirty. */ - r.x = 0; - r.y = 0; - r.height = win.ch; - r.width = width; - XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); - - /* Render the glyphs. */ - XftDrawGlyphFontSpec(xw.draw, fg, specs, len); - - /* Render underline and strikethrough. */ - if (base.mode & ATTR_UNDERLINE) { - // Underline Color - const int widthThreshold = 28; // +1 width every widthThreshold px of font - int wlw = (win.ch / widthThreshold) + 1; // Wave Line Width - int linecolor; - if ((base.ucolor[0] >= 0) && - !(base.mode & ATTR_BLINK && win.mode & MODE_BLINK) && - !(base.mode & ATTR_INVISIBLE) - ) { - // Special color for underline - // Index - if (base.ucolor[1] < 0) { - linecolor = dc.col[base.ucolor[0]].pixel; - } - // RGB - else { - XColor lcolor; - lcolor.red = base.ucolor[0] * 257; - lcolor.green = base.ucolor[1] * 257; - lcolor.blue = base.ucolor[2] * 257; - lcolor.flags = DoRed | DoGreen | DoBlue; - XAllocColor(xw.dpy, xw.cmap, &lcolor); - linecolor = lcolor.pixel; - } - } else { - // Foreground color for underline - linecolor = fg->pixel; - } - - XGCValues ugcv = { - .foreground = linecolor, - .line_width = wlw, - .line_style = LineSolid, - .cap_style = CapNotLast - }; - - GC ugc = XCreateGC(xw.dpy, XftDrawDrawable(xw.draw), - GCForeground | GCLineWidth | GCLineStyle | GCCapStyle, - &ugcv); - - // Underline Style - if (base.ustyle != 3) { - //XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1, width, 1); - XFillRectangle(xw.dpy, XftDrawDrawable(xw.draw), ugc, winx, - winy + dc.font.ascent + 1, width, wlw); - } else if (base.ustyle == 3) { - int ww = win.cw;//width; - int wh = dc.font.descent - wlw/2 - 1;//r.height/7; - int wx = winx; - int wy = winy + win.ch - dc.font.descent; - -#if UNDERCURL_STYLE == UNDERCURL_CURLY - // Draw waves - int narcs = charlen * 2 + 1; - XArc *arcs = xmalloc(sizeof(XArc) * narcs); - - int i = 0; - for (i = 0; i < charlen-1; i++) { - arcs[i*2] = (XArc) { - .x = wx + win.cw * i + ww / 4, - .y = wy, - .width = win.cw / 2, - .height = wh, - .angle1 = 0, - .angle2 = 180 * 64 - }; - arcs[i*2+1] = (XArc) { - .x = wx + win.cw * i + ww * 0.75, - .y = wy, - .width = win.cw/2, - .height = wh, - .angle1 = 180 * 64, - .angle2 = 180 * 64 - }; - } - // Last wave - arcs[i*2] = (XArc) {wx + ww * i + ww / 4, wy, ww / 2, wh, - 0, 180 * 64 }; - // Last wave tail - arcs[i*2+1] = (XArc) {wx + ww * i + ww * 0.75, wy, ceil(ww / 2.), - wh, 180 * 64, 90 * 64}; - // First wave tail - i++; - arcs[i*2] = (XArc) {wx - ww/4 - 1, wy, ceil(ww / 2.), wh, 270 * 64, - 90 * 64 }; - - XDrawArcs(xw.dpy, XftDrawDrawable(xw.draw), ugc, arcs, narcs); - - free(arcs); -#elif UNDERCURL_STYLE == UNDERCURL_SPIKY - // Make the underline corridor larger - /* - wy -= wh; - */ - wh *= 2; - - // Set the angle of the slope to 45° - ww = wh; - - // Position of wave is independent of word, it's absolute - wx = (wx / (ww/2)) * (ww/2); - - int marginStart = winx - wx; - - // Calculate number of points with floating precision - float n = width; // Width of word in pixels - n = (n / ww) * 2; // Number of slopes (/ or \) - n += 2; // Add two last points - int npoints = n; // Convert to int - - // Total length of underline - float waveLength = 0; - - if (npoints >= 3) { - // We add an aditional slot in case we use a bonus point - XPoint *points = xmalloc(sizeof(XPoint) * (npoints + 1)); - - // First point (Starts with the word bounds) - points[0] = (XPoint) { - .x = wx + marginStart, - .y = (isSlopeRising(wx, 0, ww)) - ? (wy - marginStart + ww/2.f) - : (wy + marginStart) - }; - - // Second point (Goes back to the absolute point coordinates) - points[1] = (XPoint) { - .x = (ww/2.f) - marginStart, - .y = (isSlopeRising(wx, 1, ww)) - ? (ww/2.f - marginStart) - : (-ww/2.f + marginStart) - }; - waveLength += (ww/2.f) - marginStart; - - // The rest of the points - for (int i = 2; i < npoints-1; i++) { - points[i] = (XPoint) { - .x = ww/2, - .y = (isSlopeRising(wx, i, ww)) - ? wh/2 - : -wh/2 - }; - waveLength += ww/2; - } - - // Last point - points[npoints-1] = (XPoint) { - .x = ww/2, - .y = (isSlopeRising(wx, npoints-1, ww)) - ? wh/2 - : -wh/2 - }; - waveLength += ww/2; - - // End - if (waveLength < width) { // Add a bonus point? - int marginEnd = width - waveLength; - points[npoints] = (XPoint) { - .x = marginEnd, - .y = (isSlopeRising(wx, npoints, ww)) - ? (marginEnd) - : (-marginEnd) - }; - - npoints++; - } else if (waveLength > width) { // Is last point too far? - int marginEnd = waveLength - width; - points[npoints-1].x -= marginEnd; - if (isSlopeRising(wx, npoints-1, ww)) - points[npoints-1].y -= (marginEnd); - else - points[npoints-1].y += (marginEnd); - } - - // Draw the lines - XDrawLines(xw.dpy, XftDrawDrawable(xw.draw), ugc, points, npoints, - CoordModePrevious); - - // Draw a second underline with an offset of 1 pixel - if ( ((win.ch / (widthThreshold/2)) % 2)) { - points[0].x++; - - XDrawLines(xw.dpy, XftDrawDrawable(xw.draw), ugc, points, - npoints, CoordModePrevious); - } - - // Free resources - free(points); - } -#else // UNDERCURL_CAPPED - // Cap is half of wave width - float capRatio = 0.5f; - - // Make the underline corridor larger - wh *= 2; - - // Set the angle of the slope to 45° - ww = wh; - ww *= 1 + capRatio; // Add a bit of width for the cap - - // Position of wave is independent of word, it's absolute - wx = (wx / ww) * ww; - - float marginStart; - switch(getSlope(winx, 0, ww)) { - case UNDERCURL_SLOPE_ASCENDING: - marginStart = winx - wx; - break; - case UNDERCURL_SLOPE_TOP_CAP: - marginStart = winx - (wx + (ww * (2.f/6.f))); - break; - case UNDERCURL_SLOPE_DESCENDING: - marginStart = winx - (wx + (ww * (3.f/6.f))); - break; - case UNDERCURL_SLOPE_BOTTOM_CAP: - marginStart = winx - (wx + (ww * (5.f/6.f))); - break; - } - - // Calculate number of points with floating precision - float n = width; // Width of word in pixels - // ._. - n = (n / ww) * 4; // Number of points (./ \.) - n += 2; // Add two last points - int npoints = n; // Convert to int - - // Position of the pen to draw the lines - float penX = 0; - float penY = 0; - - if (npoints >= 3) { - XPoint *points = xmalloc(sizeof(XPoint) * (npoints + 1)); - - // First point (Starts with the word bounds) - penX = winx; - switch (getSlope(winx, 0, ww)) { - case UNDERCURL_SLOPE_ASCENDING: - penY = wy + wh/2.f - marginStart; - break; - case UNDERCURL_SLOPE_TOP_CAP: - penY = wy; - break; - case UNDERCURL_SLOPE_DESCENDING: - penY = wy + marginStart; - break; - case UNDERCURL_SLOPE_BOTTOM_CAP: - penY = wy + wh/2.f; - break; - } - points[0].x = penX; - points[0].y = penY; - - // Second point (Goes back to the absolute point coordinates) - switch (getSlope(winx, 1, ww)) { - case UNDERCURL_SLOPE_ASCENDING: - penX += ww * (1.f/6.f) - marginStart; - penY += 0; - break; - case UNDERCURL_SLOPE_TOP_CAP: - penX += ww * (2.f/6.f) - marginStart; - penY += -wh/2.f + marginStart; - break; - case UNDERCURL_SLOPE_DESCENDING: - penX += ww * (1.f/6.f) - marginStart; - penY += 0; - break; - case UNDERCURL_SLOPE_BOTTOM_CAP: - penX += ww * (2.f/6.f) - marginStart; - penY += -marginStart + wh/2.f; - break; - } - points[1].x = penX; - points[1].y = penY; - - // The rest of the points - for (int i = 2; i < npoints; i++) { - switch (getSlope(winx, i, ww)) { - case UNDERCURL_SLOPE_ASCENDING: - case UNDERCURL_SLOPE_DESCENDING: - penX += ww * (1.f/6.f); - penY += 0; - break; - case UNDERCURL_SLOPE_TOP_CAP: - penX += ww * (2.f/6.f); - penY += -wh / 2.f; - break; - case UNDERCURL_SLOPE_BOTTOM_CAP: - penX += ww * (2.f/6.f); - penY += wh / 2.f; - break; - } - points[i].x = penX; - points[i].y = penY; - } - - // End - float waveLength = penX - winx; - if (waveLength < width) { // Add a bonus point? - int marginEnd = width - waveLength; - penX += marginEnd; - switch(getSlope(winx, npoints, ww)) { - case UNDERCURL_SLOPE_ASCENDING: - case UNDERCURL_SLOPE_DESCENDING: - //penY += 0; - break; - case UNDERCURL_SLOPE_TOP_CAP: - penY += -marginEnd; - break; - case UNDERCURL_SLOPE_BOTTOM_CAP: - penY += marginEnd; - break; - } - - points[npoints].x = penX; - points[npoints].y = penY; - - npoints++; - } else if (waveLength > width) { // Is last point too far? - int marginEnd = waveLength - width; - points[npoints-1].x -= marginEnd; - switch(getSlope(winx, npoints-1, ww)) { - case UNDERCURL_SLOPE_TOP_CAP: - points[npoints-1].y += marginEnd; - break; - case UNDERCURL_SLOPE_BOTTOM_CAP: - points[npoints-1].y -= marginEnd; - break; - default: - break; - } - } - - // Draw the lines - XDrawLines(xw.dpy, XftDrawDrawable(xw.draw), ugc, points, npoints, - CoordModeOrigin); - - // Draw a second underline with an offset of 1 pixel - if ( ((win.ch / (widthThreshold/2)) % 2)) { - for (int i = 0; i < npoints; i++) - points[i].x++; - - XDrawLines(xw.dpy, XftDrawDrawable(xw.draw), ugc, points, - npoints, CoordModeOrigin); - } - - // Free resources - free(points); - } -#endif - } - - XFreeGC(xw.dpy, ugc); - } - - if (base.mode & ATTR_STRUCK) { - XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent * chscale / 3, - width, 1); - } - - /* Reset clip to none. */ - XftDrawSetClip(xw.draw, 0); -} - -void -xdrawglyph(Glyph g, int x, int y) -{ - int numspecs; - XftGlyphFontSpec spec; - - numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y); - xdrawglyphfontspecs(&spec, g, numspecs, x, y); -} - -void -xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og) -{ - Color drawcol; - - /* remove the old cursor */ - if (selected(ox, oy)) - og.mode ^= ATTR_REVERSE; - xdrawglyph(og, ox, oy); - - if (IS_SET(MODE_HIDE)) - return; - - /* - * Select the right color for the right mode. - */ - g.mode &= ATTR_BOLD|ATTR_ITALIC|ATTR_UNDERLINE|ATTR_STRUCK|ATTR_WIDE; - - if (IS_SET(MODE_REVERSE)) { - g.mode |= ATTR_REVERSE; - g.bg = defaultfg; - if (selected(cx, cy)) { - drawcol = dc.col[defaultcs]; - g.fg = defaultrcs; - } else { - drawcol = dc.col[defaultrcs]; - g.fg = defaultcs; - } - } else { - if (selected(cx, cy)) { - g.fg = defaultfg; - g.bg = defaultrcs; - } else { - g.fg = defaultbg; - g.bg = defaultcs; - } - drawcol = dc.col[g.bg]; - } - - /* draw the new one */ - if (IS_SET(MODE_FOCUSED)) { - switch (win.cursor) { - case 7: /* st extension */ - g.u = 0x2603; /* snowman (U+2603) */ - /* FALLTHROUGH */ - case 0: /* Blinking Block */ - case 1: /* Blinking Block (Default) */ - case 2: /* Steady Block */ - xdrawglyph(g, cx, cy); - break; - case 3: /* Blinking Underline */ - case 4: /* Steady Underline */ - XftDrawRect(xw.draw, &drawcol, - win.hborderpx + cx * win.cw, - win.vborderpx + (cy + 1) * win.ch - \ - cursorthickness, - win.cw, cursorthickness); - break; - case 5: /* Blinking bar */ - case 6: /* Steady bar */ - XftDrawRect(xw.draw, &drawcol, - win.hborderpx + cx * win.cw, - win.vborderpx + cy * win.ch, - cursorthickness, win.ch); - break; - } - } else { - XftDrawRect(xw.draw, &drawcol, - win.hborderpx + cx * win.cw, - win.vborderpx + cy * win.ch, - win.cw - 1, 1); - XftDrawRect(xw.draw, &drawcol, - win.hborderpx + cx * win.cw, - win.vborderpx + cy * win.ch, - 1, win.ch - 1); - XftDrawRect(xw.draw, &drawcol, - win.hborderpx + (cx + 1) * win.cw - 1, - win.vborderpx + cy * win.ch, - 1, win.ch - 1); - XftDrawRect(xw.draw, &drawcol, - win.hborderpx + cx * win.cw, - win.vborderpx + (cy + 1) * win.ch - 1, - win.cw, 1); - } -} - -void -xsetenv(void) -{ - char buf[sizeof(long) * 8 + 1]; - - snprintf(buf, sizeof(buf), "%lu", xw.win); - setenv("WINDOWID", buf, 1); -} - -void -xseticontitle(char *p) -{ - XTextProperty prop; - DEFAULT(p, opt_title); - - if (p[0] == '\0') - p = opt_title; - - if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, - &prop) != Success) - return; - XSetWMIconName(xw.dpy, xw.win, &prop); - XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmiconname); - XFree(prop.value); -} - -void -xsettitle(char *p) -{ - XTextProperty prop; - DEFAULT(p, opt_title); - - if (p[0] == '\0') - p = opt_title; - - if (Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, - &prop) != Success) - return; - XSetWMName(xw.dpy, xw.win, &prop); - XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmname); - XFree(prop.value); -} - -int -xstartdraw(void) -{ - return IS_SET(MODE_VISIBLE); -} - -void -xdrawline(Line line, int x1, int y1, int x2) -{ - int i, x, ox, numspecs; - Glyph base, new; - XftGlyphFontSpec *specs = xw.specbuf; - - numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1); - i = ox = 0; - for (x = x1; x < x2 && i < numspecs; x++) { - new = line[x]; - if (new.mode == ATTR_WDUMMY) - continue; - if (selected(x, y1)) - new.mode ^= ATTR_REVERSE; - if (i > 0 && ATTRCMP(base, new)) { - xdrawglyphfontspecs(specs, base, i, ox, y1); - specs += i; - numspecs -= i; - i = 0; - } - if (i == 0) { - ox = x; - base = new; - } - i++; - } - if (i > 0) - xdrawglyphfontspecs(specs, base, i, ox, y1); -} - -void -xfinishdraw(void) -{ - XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, win.w, - win.h, 0, 0); - XSetForeground(xw.dpy, dc.gc, - dc.col[IS_SET(MODE_REVERSE)? - defaultfg : defaultbg].pixel); -} - -void -xximspot(int x, int y) -{ - if (xw.ime.xic == NULL) - return; - - xw.ime.spot.x = borderpx + x * win.cw; - xw.ime.spot.y = borderpx + (y + 1) * win.ch; - - XSetICValues(xw.ime.xic, XNPreeditAttributes, xw.ime.spotlist, NULL); -} - -void -expose(XEvent *ev) -{ - redraw(); -} - -void -visibility(XEvent *ev) -{ - XVisibilityEvent *e = &ev->xvisibility; - - MODBIT(win.mode, e->state != VisibilityFullyObscured, MODE_VISIBLE); -} - -void -unmap(XEvent *ev) -{ - win.mode &= ~MODE_VISIBLE; -} - -void -xsetpointermotion(int set) -{ - MODBIT(xw.attrs.event_mask, set, PointerMotionMask); - XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs); -} - -void -xsetmode(int set, unsigned int flags) -{ - int mode = win.mode; - MODBIT(win.mode, set, flags); - if ((win.mode & MODE_REVERSE) != (mode & MODE_REVERSE)) - redraw(); -} - -int -xsetcursor(int cursor) -{ - if (!BETWEEN(cursor, 0, 7)) /* 7: st extension */ - return 1; - win.cursor = cursor; - return 0; -} - -void -xseturgency(int add) -{ - XWMHints *h = XGetWMHints(xw.dpy, xw.win); - - MODBIT(h->flags, add, XUrgencyHint); - XSetWMHints(xw.dpy, xw.win, h); - XFree(h); -} - -void -xbell(void) -{ - if (!(IS_SET(MODE_FOCUSED))) - xseturgency(1); - if (bellvolume) - XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL); -} - -void -focus(XEvent *ev) -{ - XFocusChangeEvent *e = &ev->xfocus; - - if (e->mode == NotifyGrab) - return; - - if (ev->type == FocusIn) { - if (xw.ime.xic) - XSetICFocus(xw.ime.xic); - win.mode |= MODE_FOCUSED; - xseturgency(0); - if (IS_SET(MODE_FOCUS)) - ttywrite("\033[I", 3, 0); - } else { - if (xw.ime.xic) - XUnsetICFocus(xw.ime.xic); - win.mode &= ~MODE_FOCUSED; - if (IS_SET(MODE_FOCUS)) - ttywrite("\033[O", 3, 0); - } -} - -int -match(uint mask, uint state) -{ - return mask == XK_ANY_MOD || mask == (state & ~ignoremod); -} - -char* -kmap(KeySym k, uint state) -{ - Key *kp; - int i; - - /* Check for mapped keys out of X11 function keys. */ - for (i = 0; i < LEN(mappedkeys); i++) { - if (mappedkeys[i] == k) - break; - } - if (i == LEN(mappedkeys)) { - if ((k & 0xFFFF) < 0xFD00) - return NULL; - } - - for (kp = key; kp < key + LEN(key); kp++) { - if (kp->k != k) - continue; - - if (!match(kp->mask, state)) - continue; - - if (IS_SET(MODE_APPKEYPAD) ? kp->appkey < 0 : kp->appkey > 0) - continue; - if (IS_SET(MODE_NUMLOCK) && kp->appkey == 2) - continue; - - if (IS_SET(MODE_APPCURSOR) ? kp->appcursor < 0 : kp->appcursor > 0) - continue; - - return kp->s; - } - - return NULL; -} - -void -kpress(XEvent *ev) -{ - XKeyEvent *e = &ev->xkey; - KeySym ksym = NoSymbol; - char buf[64], *customkey; - int len; - Rune c; - Status status; - Shortcut *bp; - - if (IS_SET(MODE_KBDLOCK)) - return; - - if (xw.ime.xic) { - len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status); - if (status == XBufferOverflow) - return; - } else { - len = XLookupString(e, buf, sizeof buf, &ksym, NULL); - } - - if ( IS_SET(MODE_KBDSELECT) ) { - if ( match(XK_NO_MOD, e->state) || - (XK_Shift_L | XK_Shift_R) & e->state ) - win.mode ^= trt_kbdselect(ksym, buf, len); - return; - } - - /* 1. shortcuts */ - for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) { - if (ksym == bp->keysym && match(bp->mod, e->state)) { - bp->func(&(bp->arg)); - return; - } - } - - /* 2. custom keys from config.h */ - if ((customkey = kmap(ksym, e->state))) { - ttywrite(customkey, strlen(customkey), 1); - return; - } - - /* 3. composed string from input method */ - if (len == 0) - return; - if (len == 1 && e->state & Mod1Mask) { - if (IS_SET(MODE_8BIT)) { - if (*buf < 0177) { - c = *buf | 0x80; - len = utf8encode(c, buf); - } - } else { - buf[1] = buf[0]; - buf[0] = '\033'; - len = 2; - } - } - ttywrite(buf, len, 1); -} - -void -cmessage(XEvent *e) -{ - /* - * See xembed specs - * http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html - */ - if (e->xclient.message_type == xw.xembed && e->xclient.format == 32) { - if (e->xclient.data.l[1] == XEMBED_FOCUS_IN) { - win.mode |= MODE_FOCUSED; - xseturgency(0); - } else if (e->xclient.data.l[1] == XEMBED_FOCUS_OUT) { - win.mode &= ~MODE_FOCUSED; - } - } else if (e->xclient.data.l[0] == xw.wmdeletewin) { - ttyhangup(); - exit(0); - } -} - -void -resize(XEvent *e) -{ - if (e->xconfigure.width == win.w && e->xconfigure.height == win.h) - return; - - cresize(e->xconfigure.width, e->xconfigure.height); -} - -void -run(void) -{ - XEvent ev; - int w = win.w, h = win.h; - fd_set rfd; - int xfd = XConnectionNumber(xw.dpy), ttyfd, xev, drawing; - struct timespec seltv, *tv, now, lastblink, trigger; - double timeout; - - /* Waiting for window mapping */ - do { - XNextEvent(xw.dpy, &ev); - /* - * This XFilterEvent call is required because of XOpenIM. It - * does filter out the key event and some client message for - * the input method too. - */ - if (XFilterEvent(&ev, None)) - continue; - if (ev.type == ConfigureNotify) { - w = ev.xconfigure.width; - h = ev.xconfigure.height; - } - } while (ev.type != MapNotify); - - ttyfd = ttynew(opt_line, shell, opt_io, opt_cmd); - cresize(w, h); - - for (timeout = -1, drawing = 0, lastblink = (struct timespec){0};;) { - FD_ZERO(&rfd); - FD_SET(ttyfd, &rfd); - FD_SET(xfd, &rfd); - - if (XPending(xw.dpy)) - timeout = 0; /* existing events might not set xfd */ - - seltv.tv_sec = timeout / 1E3; - seltv.tv_nsec = 1E6 * (timeout - 1E3 * seltv.tv_sec); - tv = timeout >= 0 ? &seltv : NULL; - - if (pselect(MAX(xfd, ttyfd)+1, &rfd, NULL, NULL, tv, NULL) < 0) { - if (errno == EINTR) - continue; - die("select failed: %s\n", strerror(errno)); - } - clock_gettime(CLOCK_MONOTONIC, &now); - - if (FD_ISSET(ttyfd, &rfd)) - ttyread(); - - xev = 0; - while (XPending(xw.dpy)) { - xev = 1; - XNextEvent(xw.dpy, &ev); - if (XFilterEvent(&ev, None)) - continue; - if (handler[ev.type]) - (handler[ev.type])(&ev); - } - - /* - * To reduce flicker and tearing, when new content or event - * triggers drawing, we first wait a bit to ensure we got - * everything, and if nothing new arrives - we draw. - * We start with trying to wait minlatency ms. If more content - * arrives sooner, we retry with shorter and shorter periods, - * and eventually draw even without idle after maxlatency ms. - * Typically this results in low latency while interacting, - * maximum latency intervals during `cat huge.txt`, and perfect - * sync with periodic updates from animations/key-repeats/etc. - */ - if (FD_ISSET(ttyfd, &rfd) || xev) { - if (!drawing) { - trigger = now; - drawing = 1; - } - timeout = (maxlatency - TIMEDIFF(now, trigger)) \ - / maxlatency * minlatency; - if (timeout > 0) - continue; /* we have time, try to find idle */ - } - - /* idle detected or maxlatency exhausted -> draw */ - timeout = -1; - if (blinktimeout && tattrset(ATTR_BLINK)) { - timeout = blinktimeout - TIMEDIFF(now, lastblink); - if (timeout <= 0) { - if (-timeout > blinktimeout) /* start visible */ - win.mode |= MODE_BLINK; - win.mode ^= MODE_BLINK; - tsetdirtattr(ATTR_BLINK); - lastblink = now; - timeout = blinktimeout; - } - } - - draw(); - XFlush(xw.dpy); - drawing = 0; - } -} - -void -usage(void) -{ - die("usage: %s [-aiv] [-c class] [-f font] [-g geometry]" - " [-n name] [-o file]\n" - " [-T title] [-t title] [-w windowid]" - " [[-e] command [args ...]]\n" - " %s [-aiv] [-c class] [-f font] [-g geometry]" - " [-n name] [-o file]\n" - " [-T title] [-t title] [-w windowid] -l line" - " [stty_args ...]\n", argv0, argv0); -} - -void toggle_winmode(int flag) { - win.mode ^= flag; -} - -void keyboard_select(const Arg *dummy) { - win.mode ^= trt_kbdselect(-1, NULL, 0); -} - -int -main(int argc, char *argv[]) -{ - xw.l = xw.t = 0; - xw.isfixed = False; - xsetcursor(cursorshape); - - ARGBEGIN { - case 'a': - allowaltscreen = 0; - break; - case 'c': - opt_class = EARGF(usage()); - break; - case 'e': - if (argc > 0) - --argc, ++argv; - goto run; - case 'f': - opt_font = EARGF(usage()); - break; - case 'g': - xw.gm = XParseGeometry(EARGF(usage()), - &xw.l, &xw.t, &cols, &rows); - break; - case 'i': - xw.isfixed = 1; - break; - case 'o': - opt_io = EARGF(usage()); - break; - case 'l': - opt_line = EARGF(usage()); - break; - case 'n': - opt_name = EARGF(usage()); - break; - case 't': - case 'T': - opt_title = EARGF(usage()); - break; - case 'w': - opt_embed = EARGF(usage()); - break; - case 'v': - die("%s " VERSION "\n", argv0); - break; - default: - usage(); - } ARGEND; - -run: - if (argc > 0) /* eat all remaining arguments */ - opt_cmd = argv; - - if (!opt_title) - opt_title = (opt_line || !opt_cmd) ? "st" : opt_cmd[0]; - - setlocale(LC_CTYPE, ""); - XSetLocaleModifiers(""); - cols = MAX(cols, 1); - rows = MAX(rows, 1); - tnew(cols, rows); - xinit(cols, rows); - xsetenv(); - selinit(); - run(); - - return 0; -} diff --git a/symlinks.csv b/symlinks.csv index 84ad337..aca99bf 100644 --- a/symlinks.csv +++ b/symlinks.csv @@ -1,17 +1,17 @@ -emacs,.emacs.d -bash_profile,.bash_profile -bashrc,.bashrc -bash_aliases,.bash_aliases -xinitrc,.xinitrc -Xdefaults,.Xdefaults -alacritty,.config/alacritty -qutebrowser,.config/qutebrowser -fbterm/fbtermrc,.config/fbtermrc -fbterm/fbterm-emacs.sh,.local/bin/fbterm-emacs.sh -brightness/brightnessup,.local/bin/brightnessup -brightness/brightnessdown,.local/bin/brightnessdown -brightness/brightnessmax,.local/bin/brightnessmax -volume/volumeup,.local/bin/volumeup -volume/volumedown,.local/bin/volumedown -volume/volumemute,.local/bin/volumemute -misc/lk.sh,.local/bin/lk +config/emacs,.emacs.d +config/bash_profile,.bash_profile +config/bashrc,.bashrc +config/bash_aliases,.bash_aliases +config/xinitrc,.xinitrc +config/Xdefaults,.Xdefaults +config/alacritty,.config/alacritty +config/qutebrowser,.config/qutebrowser +config/fbterm/fbtermrc,.config/fbtermrc +config/fbterm/fbterm-emacs.sh,.local/bin/fbterm-emacs.sh +scripts/brightness/brightnessup,.local/bin/brightnessup +scripts/brightness/brightnessdown,.local/bin/brightnessdown +scripts/brightness/brightnessmax,.local/bin/brightnessmax +scripts/volume/volumeup,.local/bin/volumeup +scripts/volume/volumedown,.local/bin/volumedown +scripts/volume/volumemute,.local/bin/volumemute +scripts/misc/lk.sh,.local/bin/lk diff --git a/xmonad/build b/xmonad/build deleted file mode 100755 index 4e8ab6c..0000000 --- a/xmonad/build +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -cd "$HOME/.xmonad" && cabal build || exit -ln -sfT "$(cabal list-bin xmonad)" "$1" |
