summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore44
-rw-r--r--.gitmodules14
-rw-r--r--config/Xdefaults (renamed from Xdefaults)0
l---------config/alacritty/alacritty1
-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.lock1
l---------config/emacs/emacs1
-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/history22
-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-xconfig/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-xconfig/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)bin376185 -> 376185 bytes
-rw-r--r--config/emacs/templates/c.eld (renamed from emacs/templates/c.eld)0
-rw-r--r--config/emacs/viper1
-rwxr-xr-xconfig/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.ts13955
-rw-r--r--config/glide/glide.ts (renamed from glide/glide.ts)0
-rw-r--r--config/glirc/config18
-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/qutebrowser1
-rw-r--r--config/sway/config (renamed from sway/config)0
-rwxr-xr-xconfig/sway/otherwindow (renamed from sway/otherwindow)0
-rwxr-xr-xconfig/sway/switch.py (renamed from sway/switch.py)0
-rwxr-xr-xconfig/sway/switch.sh (renamed from sway/switch.sh)0
-rwxr-xr-xconfig/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-xconfig/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.gzbin26379 -> 0 bytes
-rw-r--r--dwm/dwm-6.6/LICENSE38
-rw-r--r--dwm/dwm-6.6/Makefile45
-rw-r--r--dwm/dwm-6.6/README48
-rw-r--r--dwm/dwm-6.6/config.def.h136
-rw-r--r--dwm/dwm-6.6/config.mk39
-rw-r--r--dwm/dwm-6.6/drw.c448
-rw-r--r--dwm/dwm-6.6/drw.h58
-rw-r--r--dwm/dwm-6.6/dwm.1176
-rw-r--r--dwm/dwm-6.6/dwm.c2277
-rw-r--r--dwm/dwm-6.6/dwm.pngbin373 -> 0 bytes
-rw-r--r--dwm/dwm-6.6/movestack.c49
-rw-r--r--dwm/dwm-6.6/transient.c42
-rw-r--r--dwm/dwm-6.6/util.c37
-rw-r--r--dwm/dwm-6.6/util.h9
-rwxr-xr-xdwm/setup.sh9
-rwxr-xr-xniceties/capslock/caps2esc7
m---------niceties/capslock/caps2esc-tools0
-rwxr-xr-xniceties/capslock/caps2escd5
m---------niceties/capslock/interception-tools0
-rw-r--r--niceties/capslock/udevmon.yaml6
-rwxr-xr-xniceties/setup.sh25
m---------niceties/unclutter-xfixes0
-rwxr-xr-xscripts/brightness/brightnessdown (renamed from brightness/brightnessdown)0
-rwxr-xr-xscripts/brightness/brightnessmax (renamed from brightness/brightnessmax)0
-rwxr-xr-xscripts/brightness/brightnessup (renamed from brightness/brightnessup)0
-rwxr-xr-xscripts/misc/lk.sh (renamed from misc/lk.sh)0
-rwxr-xr-xscripts/volume/volumedown (renamed from volume/volumedown)0
-rwxr-xr-xscripts/volume/volumemute (renamed from volume/volumemute)0
-rwxr-xr-xscripts/volume/volumeup (renamed from volume/volumeup)0
-rwxr-xr-xsetup.sh62
-rwxr-xr-xslstatus/setup.sh9
-rw-r--r--slstatus/slstatus-1.1.tar.gzbin18407 -> 0 bytes
-rw-r--r--slstatus/slstatus-1.1/LICENSE46
-rw-r--r--slstatus/slstatus-1.1/Makefile69
-rw-r--r--slstatus/slstatus-1.1/README65
-rw-r--r--slstatus/slstatus-1.1/arg.h33
-rw-r--r--slstatus/slstatus-1.1/components/battery.c247
-rw-r--r--slstatus/slstatus-1.1/components/cat.c32
-rw-r--r--slstatus/slstatus-1.1/components/cpu.c157
-rw-r--r--slstatus/slstatus-1.1/components/datetime.c20
-rw-r--r--slstatus/slstatus-1.1/components/disk.c59
-rw-r--r--slstatus/slstatus-1.1/components/entropy.c29
-rw-r--r--slstatus/slstatus-1.1/components/hostname.c17
-rw-r--r--slstatus/slstatus-1.1/components/ip.c87
-rw-r--r--slstatus/slstatus-1.1/components/kernel_release.c19
-rw-r--r--slstatus/slstatus-1.1/components/keyboard_indicators.c50
-rw-r--r--slstatus/slstatus-1.1/components/keymap.c86
-rw-r--r--slstatus/slstatus-1.1/components/load_avg.c19
-rw-r--r--slstatus/slstatus-1.1/components/netspeeds.c129
-rw-r--r--slstatus/slstatus-1.1/components/num_files.c32
-rw-r--r--slstatus/slstatus-1.1/components/ram.c212
-rw-r--r--slstatus/slstatus-1.1/components/run_command.c31
-rw-r--r--slstatus/slstatus-1.1/components/swap.c274
-rw-r--r--slstatus/slstatus-1.1/components/temperature.c73
-rw-r--r--slstatus/slstatus-1.1/components/uptime.c34
-rw-r--r--slstatus/slstatus-1.1/components/user.c33
-rw-r--r--slstatus/slstatus-1.1/components/volume.c219
-rw-r--r--slstatus/slstatus-1.1/components/wifi.c413
-rw-r--r--slstatus/slstatus-1.1/config.def.h74
-rw-r--r--slstatus/slstatus-1.1/config.mk22
-rw-r--r--slstatus/slstatus-1.1/slstatus.147
-rw-r--r--slstatus/slstatus-1.1/slstatus.c135
-rw-r--r--slstatus/slstatus-1.1/slstatus.h85
-rw-r--r--slstatus/slstatus-1.1/util.c141
-rw-r--r--slstatus/slstatus-1.1/util.h16
-rwxr-xr-xst/setup.sh9
-rw-r--r--st/st-0.9.3.tar.gzbin49528 -> 0 bytes
-rw-r--r--st/st-0.9.3/FAQ253
-rw-r--r--st/st-0.9.3/LEGACY17
-rw-r--r--st/st-0.9.3/LICENSE34
-rw-r--r--st/st-0.9.3/Makefile51
-rw-r--r--st/st-0.9.3/README34
-rw-r--r--st/st-0.9.3/TODO28
-rw-r--r--st/st-0.9.3/arg.h50
-rw-r--r--st/st-0.9.3/config.def.h503
-rw-r--r--st/st-0.9.3/config.mk36
-rw-r--r--st/st-0.9.3/st.1177
-rw-r--r--st/st-0.9.3/st.c3414
-rw-r--r--st/st-0.9.3/st.h136
-rw-r--r--st/st-0.9.3/st.info244
-rw-r--r--st/st-0.9.3/win.h44
-rw-r--r--st/st-0.9.3/x.c2532
-rw-r--r--symlinks.csv34
-rwxr-xr-xxmonad/build3
141 files changed, 14078 insertions, 14112 deletions
diff --git a/.gitignore b/.gitignore
index c711dcd..cd678db 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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/bashrc b/config/bashrc
index b148117..b148117 100644
--- a/bashrc
+++ b/config/bashrc
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
index 4b5de18..4b5de18 100644
--- a/emacs/splashLaputa.png
+++ b/config/emacs/splashLaputa.png
Binary files differ
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 &mdash; for example, <em>messageName</em>
+ * is not a string or the <em>substitutions</em> array has more than 9 elements &mdash; 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)[&lt;all_urls&gt;]
+ * 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 &lt;all_urls&gt; 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 &lt;iframe&gt; or a &lt;frame&gt; 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 &mdash; 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&mdash;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>&lt;link rel='prefetch' ...&gt;</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>&lt;a ping&gt;</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/xinitrc b/config/xinitrc
index 9f7e1d3..9f7e1d3 100644
--- a/xinitrc
+++ b/config/xinitrc
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
deleted file mode 100644
index 966b256..0000000
--- a/dwm/dwm-6.6.tar.gz
+++ /dev/null
Binary files differ
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
deleted file mode 100644
index b1f9ba7..0000000
--- a/dwm/dwm-6.6/dwm.png
+++ /dev/null
Binary files differ
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
diff --git a/setup.sh b/setup.sh
index 665882d..2912a27 100755
--- a/setup.sh
+++ b/setup.sh
@@ -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
deleted file mode 100644
index 2ac5bfc..0000000
--- a/slstatus/slstatus-1.1.tar.gz
+++ /dev/null
Binary files differ
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", &current_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, &current) < 0)
- die("clock_gettime:");
- difftimespec(&diff, &current, &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
deleted file mode 100644
index ca8cd05..0000000
--- a/st/st-0.9.3.tar.gz
+++ /dev/null
Binary files differ
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"